untitled-923index.ts4 matches
25});
2627// API endpoints for future enhancements
28app.get("/api/programs", c => {
29const programs = [
30{
60});
6162app.post("/api/contact", async c => {
63const body = await c.req.json();
64
7374// Health check endpoint
75app.get("/api/health", c => {
76return c.json({ status: "healthy", timestamp: new Date().toISOString() });
77});
untitled-923Hero.tsx1 match
20<p className="text-xl md:text-2xl mb-8 max-w-3xl mx-auto leading-relaxed">
21Excellence in Education, Innovation in Learning.
22Shaping tomorrow's leaders in Management and Science.
23</p>
24
charmaineValSearchcomponents.tsx8 matches
1043<link rel="icon" href="https://fav.farm/👀" />
1044<meta name="viewport" content="width=device-width, initial-scale=1" />
1045<link rel="preconnect" href="https://fonts.googleapis.com" />
1046<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
1047<link
1048href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:ital,wght@0,100..700;1,100..700&display=swap"
1049rel="stylesheet"
1050/>
1061<a href="https://val.town" className="valtown-link" style={{ marginLeft: "auto" }}>Return to Val Town</a>
1062</h1>
1063<div className="api-info">
1064<details>
1065<summary>API Access</summary>
1066<div className="api-docs">
1067<p>
1068You can access search results via JSON API by adding <code>format=json</code> to your query:
1069</p>
1070{searchTerm
1222<div className="search-examples">
1223<a href="?q=fetch" className="example-link">fetch</a>
1224<a href="?q=api" className="example-link">api</a>
1225<a href="?q=database" className="example-link">database</a>
1226<a href="?q=image" className="example-link">image</a>
1376<div className="search-examples">
1377<a href="?q=fetch" className="example-link">fetch</a>
1378<a href="?q=api" className="example-link">api</a>
1379<a href="?q=database" className="example-link">database</a>
1380<a href="?q=image" className="example-link">image</a>
GitHubSyncREADME.md3 matches
24- Ensure the token has read/write access to _Contents_ for the repo
25- Copy the access token and add that as the `GITHUB_TOKEN` env var in this val
261. Add a new [Val Town API token][] with read/write permissions. Add that token to the val's env vars as `VALTOWN_TOKEN`
271. Add a `VAL_SECRET` env var to the val. Use this secret to sign the webhook POST request to the `/push` endpoint. Use this endpoint to commit vals from Val Town to your GitHub repo.
286869- `GITHUB_TOKEN`: Read/write GitHub personal access token for reading and writing repo contents
70- `VALTOWN_TOKEN`: ValTown API token (with read/write Vals permissions) for writing updates from GitHub
71- `GITHUB_WEBHOOK_SECRET`: secret for verifying webhooks from GitHub
72- `VAL_SECRET`: secret for verifying requests to the `/push` endpoint
98[github oauth app]: https://github.com/settings/developers
99[access token]: https://github.com/settings/tokens
100[val town api token]: https://www.val.town/settings/api
101[troubleshooting]: #troubleshooting
102
templateTwitterAlertREADME.md4 matches
31Refer to [Twitter's search operators](https://socialdata.gitbook.io/docs/twitter-tweets/retrieve-search-results-by-keyword#endpoint-parameters) to fine-tune your query.
3233### 4. Test API call
34Set `isProd = false` in the code if you are testing, to ensure there are enough tweets to display. <br>
35Toggle it back to `true` when you're ready to run this cron job in production and actuall send notifications.
6061### NOTE: Usage Limits
62This val uses the SocialData API for Twitter data:
6364- **Proxies via Val Town's [SocialDataProxy](https://www.val.town/v/stevekrouse/socialDataProxy)**: Limited to 10 cents per day for [**Val Town Pro users**](https://www.val.town/pricing). This API is *only* for Pro users.
65- **Need more calls?** Sign up for your own [SocialData API token](https://socialdata.tools) and configure the [`socialDataSearch`](https://www.val.town/v/stevekrouse/socialDataSearch) function.
LiveStormMCPmcp.ts16 matches
1import { McpServer, ResourceTemplate } from "npm:@modelcontextprotocol/sdk/server/mcp.js";
2import { extractGetEndpoints, extractMutationEndpoints, fetchOpenApiSpec, proxyRequest } from "./livestorm.ts";
3import { z } from "npm:zod";
4import type { OperationObject, SchemaObject } from "./types.ts";
2021/**
22* Sets up the MCP server with resources and tools based on the Livestorm API
23* Uses a cached instance if available
24*/
31// Create a new MCP server
32const server = new McpServer({
33name: "livestorm-api-server",
34version: "1.0.0",
35description: "MCP server that provides access to Livestorm API endpoints",
36},
37{ capabilities: { logging: {} } });
3839try {
40console.log("Fetching Livestorm API OpenAPI spec...");
41// Fetch the OpenAPI spec
42const openApiSpec = await fetchOpenApiSpec();
4344// Extract GET endpoints (Resources)
45const getEndpoints = extractGetEndpoints(openApiSpec);
4647// Extract mutation endpoints (Tools)
48const mutationEndpoints = extractMutationEndpoints(openApiSpec);
4950// Register Resources
123}
124
125// Make the request to the Livestorm API
126const response = await proxyRequest(
127path,
132if (!response.ok) {
133const errorText = await response.text();
134throw new Error(`Livestorm API error: ${response.status} ${response.statusText} - ${errorText}`);
135}
136215}
216
217// Make the request to the Livestorm API
218const response = await proxyRequest(
219path,
225if (!response.ok) {
226const errorText = await response.text();
227throw new Error(`Livestorm API error: ${response.status} ${response.statusText} - ${errorText}`);
228}
229255// Convert to title case
256.replace(/^[a-z]+/, (verb) => verb.charAt(0).toUpperCase() + verb.slice(1))
257// Replace underscores with spaces and capitalize each word
258.replace(/_/g, ' ');
259}
260261/**
262* Creates a Zod schema from an OpenAPI schema object
263*/
264function createZodSchema(schemaObj?: SchemaObject): ZodTypeAny {
315316/**
317* Creates a tool schema from an OpenAPI operation
318* Returns an object with input and output schemas using Zod
319*
LiveStormMCPtypes.ts3 matches
12// Types for OpenAPI schema
3export interface OpenApiSchema {
4paths: Record<string, PathItem>;
5// Other OpenAPI properties we might need
6}
7
41advice: async () => {
42console.log("handler.advice");
43const res = await fetch("https://api.adviceslip.com/advice");
44if (!res.ok) {
45console.error("advice fetch failed", res.status);
64trivia: async () => {
65console.log("handler.trivia");
66const res = await fetch("http://numbersapi.com/random/trivia?json");
67if (!res.ok) {
68console.error("trivia fetch failed", res.status);
74compliment: async () => {
75console.log("handler.compliment");
76const res = await fetch("https://complimentr.com/api");
77if (!res.ok) {
78console.error("compliment fetch failed", res.status);
215216try {
217const res = await fetch(`https://ohmanda.com/api/horoscope/${sign}`);
218if (!res.ok) {
219console.error("horoscope fetch failed", res.status);
LiveStormMCPlivestorm.ts32 matches
1import { parse as parseYaml } from 'https://esm.sh/yaml@2.3.1';
2import { OpenApiSchema, OperationObject } from './types.ts';
3import { blob } from "https://esm.town/v/std/blob";
4import { ValTownBlobNotFoundError } from "https://esm.town/v/std/ValTownBlobNotFoundError";
56// URL of the Livestorm API OpenAPI definition
7const LIVESTORM_API_SPEC_URL = 'https://api.livestorm.co/api-docs/v1/swagger.yaml';
8const LIVESTORM_API_BASE_URL = 'https://api.livestorm.co/v1';
910// Cache key for storing the OpenAPI spec in Blob storage
11const OPENAPI_SPEC_CACHE_KEY = 'livestorm-openapi-spec';
1213/**
14* Fetches the Livestorm API OpenAPI definition
15*/
16export async function fetchOpenApiSpec(): Promise<OpenApiSchema> {
17try {
18// Check if the OpenAPI spec is cached in Blob storage
19let response;
20try {
21response = await blob.get(OPENAPI_SPEC_CACHE_KEY);
22console.log(`Using cached OpenAPI spec from Blob storage`);
23} catch (e) {
24if (e instanceof ValTownBlobNotFoundError) {
25console.log(`Fetching OpenAPI spec from ${LIVESTORM_API_SPEC_URL}...`);
26response = await fetch(LIVESTORM_API_SPEC_URL);
27if (!response.ok) {
28const errorText = await response.text();
29console.error(`Failed to fetch OpenAPI spec: ${response.status} ${response.statusText}`);
30console.error(`Response body: ${errorText}`);
31throw new Error(`Failed to fetch OpenAPI spec: ${response.status} ${response.statusText}`);
32}
33} else {
39
40try {
41const parsedSpec = parseYaml(yamlText) as OpenApiSchema;
42
43// Validate the parsed spec has the expected structure
44if (!parsedSpec || !parsedSpec.paths) {
45throw new Error('Invalid OpenAPI spec: missing paths property');
46}
47
48// Cache the OpenAPI spec in Blob storage
49await blob.set(OPENAPI_SPEC_CACHE_KEY, yamlText);
50
51return parsedSpec;
52} catch (parseError) {
53console.error('Error parsing OpenAPI spec YAML:', parseError);
54console.error('YAML content (first 500 chars):', yamlText.substring(0, 500));
55throw new Error(`Failed to parse OpenAPI spec: ${parseError instanceof Error ? parseError.message : String(parseError)}`);
56}
57} catch (error) {
58console.error('Error fetching OpenAPI spec:', error);
59throw error;
60}
6263/**
64* Extracts GET endpoints from the OpenAPI spec
65*/
66export function extractGetEndpoints(spec: OpenApiSchema) {
67const getEndpoints: Record<string, { path: string; operation: OperationObject }> = {};
68
8081/**
82* Extracts POST, PUT, DELETE endpoints from the OpenAPI spec
83*/
84export function extractMutationEndpoints(spec: OpenApiSchema) {
85const mutationEndpoints: Record<string, { method: string; path: string; operation: OperationObject }> = {};
86
119120/**
121* Proxies a request to the Livestorm API
122*/
123export async function proxyRequest(
128): Promise<Response> {
129// Replace path parameters in the URL
130let url = `${LIVESTORM_API_BASE_URL}${path}`;
131
132// Extract path parameters and replace them in the URL
157
158// Forward the Authorization header
159const authHeader = Deno.env.get("LIVESTORM_API_TOKEN");
160if (!authHeader) {
161throw new Error('Authorization header is required for Livestorm API requests');
162}
163requestHeaders.set('Authorization', authHeader);
180
181try {
182// Make the request to Livestorm API
183const response = await fetch(url, requestOptions);
184
187} catch (error) {
188console.error(`Error proxying request to ${url}:`, error);
189throw new Error(`Failed to proxy request to Livestorm API: ${error instanceof Error ? error.message : String(error)}`);
190}
191}
charmaineValSearchimport.ts1 match
39profile_image_url: user.profileImageUrl,
40url: user.url,
41updated_at: new Date().toISOString(), // Using current time as the API doesn't provide updated_at
42});
43