val-town-http-mcp-servertypes.ts2 matches
12export interface Config {
3apiToken: string | null
4apiBase: string
5cli?: {
6preferCli: boolean
val-town-http-mcp-serverapi.ts11 matches
1import {Config} from "./types.ts"
23export async function callValTownApi(
4config: Config,
5path: string,
7): Promise<any> {
8// Path conversion for endpoints that have changed in v2
9let apiPath = path
1011// If any old v1 paths are accidentally used, convert them to v2
12if (path.startsWith("/v1/projects")) {
13apiPath = path.replace("/v1/projects", "/v2/vals")
14console.warn(`Converting deprecated v1 path to v2: ${path} → ${apiPath}`)
15} else if (path.startsWith("/v1/alias/projects")) {
16apiPath = path.replace("/v1/alias/projects", "/v2/alias/vals")
17console.warn(`Converting deprecated v1 path to v2: ${path} → ${apiPath}`)
18}
1920const url = `${config.apiBase}${apiPath}`
2122if (!config.apiToken) {
23throw new Error("API token is required for ValTown API calls");
24}
2526const headers: HeadersInit = {
27'Authorization': `Bearer ${config.apiToken}`,
28'Content-Type': 'application/json',
29}
39if (!response.ok) {
40const errorText = await response.text()
41throw new Error(`API error (${response.status}): ${errorText}`)
42}
43
val-town-http-mcp-servervalsTools.ts27 matches
1import {McpServer} from "@modelcontextprotocol/sdk/server/mcp.js"
2import {Config} from "../lib/types.ts"
3import {callValTownApi} from "../lib/api.ts"
4import {getErrorMessage} from "../lib/errorUtils.ts"
5import {getCliAvailability, runVtCommand, parseCliJsonOutput} from "../lib/vtCli.ts"
37}
38
39console.error(`CLI error when getting val, falling back to API: ${result.error}`);
40// Fall back to API on error
41} catch (error) {
42console.error("CLI error, falling back to API:", getErrorMessage(error));
43// Fall back to API on error
44}
45}
4647// API implementation (original code)
48try {
49const data = await callValTownApi(
50config,
51`/v2/alias/vals/${encodeURIComponent(username)}/${encodeURIComponent(valName)}`
75async ({query, limit, offset}) => {
76try {
77const data = await callValTownApi(
78config,
79`/v1/search/vals?query=${encodeURIComponent(query)}&limit=${limit}&offset=${offset}`
135}
136
137console.error(`CLI error when creating val, falling back to API: ${result.error}`);
138// Fall back to API on error
139} catch (error) {
140console.error("CLI error, falling back to API:", getErrorMessage(error));
141// Fall back to API on error
142}
143}
144145// API implementation (original code)
146try {
147const requestBody = {
151}
152153const data = await callValTownApi(
154config,
155`/v2/vals`,
192
193// Use prepareValWorkspace first (would need to implement special workspace setup)
194// For now, we'll use the API implementation instead of complex workspace management
195
196// This could be implemented with temporary directory setup if needed,
197// but for now we'll use the API for deletion as it's simpler
198console.log("Deletion via CLI requires workspace setup, using API instead");
199} catch (error) {
200console.error("CLI error, falling back to API:", getErrorMessage(error));
201// Fall back to API on error
202}
203}
204205// API implementation (original code)
206try {
207await callValTownApi(
208config,
209`/v2/vals/${valId}`,
265}
266
267console.error(`CLI error when listing vals, falling back to API: ${result.error}`);
268// Fall back to API on error
269} catch (error) {
270console.error("CLI error, falling back to API:", getErrorMessage(error));
271// Fall back to API on error
272}
273}
274275// API implementation (original code)
276try {
277const data = await callValTownApi(
278config,
279`/v2/me/vals?limit=${limit}&offset=${offset}`
2import {z} from "zod"
3import {Config} from "../lib/types.ts"
4import {callValTownApi} from "../lib/api.ts"
5import {getErrorMessage} from "../lib/errorUtils.ts"
615async ({statement}: {statement: string}) => {
16try {
17const data = await callValTownApi(config, "/v1/sqlite/execute", {
18method: "POST",
19body: JSON.stringify({statement}),
46}) => {
47try {
48const data = await callValTownApi(config, "/v1/sqlite/batch", {
49method: "POST",
50body: JSON.stringify({statements, mode}),
73async ({statement}: {statement: string}) => {
74try {
75const data = await callValTownApi(config, "/v1/sqlite/query", {
76method: "POST",
77body: JSON.stringify({statement}),
104}) => {
105try {
106const data = await callValTownApi(config, "/v1/sqlite/exec", {
107method: "POST",
108body: JSON.stringify({statements, mode}),
val-town-http-mcp-serverbranchTools.ts22 matches
1import {McpServer} from "@modelcontextprotocol/sdk/server/mcp.js"
2import {Config} from "../lib/types.ts"
3import {callValTownApi} from "../lib/api.ts"
4import {getErrorMessage} from "../lib/errorUtils.ts"
5import {getCliAvailability, runVtCommand, parseCliJsonOutput, prepareValWorkspace, cleanupTempDirectory} from "../lib/vtCli.ts"
48}
49
50console.error(`CLI error when listing branches, falling back to API: ${workspace.error || "Unknown error"}`);
51// Fall back to API on error
52} catch (error) {
53console.error("CLI error, falling back to API:", getErrorMessage(error));
54// Fall back to API on error
55}
56}
5758// API implementation (original code)
59try {
60const data = await callValTownApi(
61config,
62`/v2/vals/${valId}/branches?limit=${limit}&offset=${offset}`
85async ({valId, branchId}) => {
86try {
87const data = await callValTownApi(
88config,
89`/v2/vals/${valId}/branches/${branchId}`
132console.error(`Failed to checkout source branch: ${checkoutResult.error}`);
133await cleanupTempDirectory(workspace.workspacePath);
134// Fall back to API
135console.error("CLI error when checking out source branch, falling back to API");
136throw new Error("Failed to checkout source branch");
137}
155}
156
157console.error(`CLI error when creating branch, falling back to API: ${workspace.error || "Unknown error"}`);
158// Fall back to API on error
159} catch (error) {
160console.error("CLI error, falling back to API:", getErrorMessage(error));
161// Fall back to API on error
162}
163}
164165// API implementation (original code)
166try {
167const requestBody = {
170}
171172const data = await callValTownApi(
173config,
174`/v2/vals/${valId}/branches`,
227}
228
229console.error(`CLI error when deleting branch, falling back to API: ${workspace.error || "Unknown error"}`);
230// Fall back to API on error
231} catch (error) {
232console.error("CLI error, falling back to API:", getErrorMessage(error));
233// Fall back to API on error
234}
235}
236237// API implementation (original code)
238try {
239await callValTownApi(
240config,
241`/v2/vals/${valId}/branches/${branchId}`,
val-town-http-mcp-serverfileTools.ts30 matches
1import {McpServer} from "@modelcontextprotocol/sdk/server/mcp.js"
2import {Config} from "../lib/types.ts"
3import {callValTownApi} from "../lib/api.ts"
4import {getErrorMessage} from "../lib/errorUtils.ts"
5import {getCliAvailability, runVtCommand, parseCliJsonOutput, prepareValWorkspace, cleanupTempDirectory} from "../lib/vtCli.ts"
122console.error(`Failed to checkout branch: ${checkoutResult.error}`)
123await cleanupTempDirectory(workspace.workspacePath!)
124// Fall back to API
125console.error("CLI error when checking out branch, falling back to API")
126throw new Error("Failed to checkout branch")
127}
147}
148149console.error(`CLI error when listing files, falling back to API: ${workspace.error || "Unknown error"}`)
150// Fall back to API on error
151} catch (error) {
152console.error("CLI error, falling back to API:", getErrorMessage(error))
153// Fall back to API on error
154}
155}
156157// API implementation (original code)
158try {
159let queryParams = `?path=${encodeURIComponent(path)}&recursive=${recursive}&limit=${limit}&offset=${offset}`
162}
163164const data = await callValTownApi(
165config,
166`/v2/vals/${valId}/files${queryParams}`
197198const response = await fetch(
199`${config.apiBase}/v2/vals/${valId}/files/content${queryParams}`,
200{
201headers: {
202'Authorization': `Bearer ${config.apiToken}`,
203},
204}
207if (!response.ok) {
208const errorText = await response.text()
209throw new Error(`API error (${response.status}): ${errorText}`)
210}
211295}
296} else {
297console.error(`CLI error when creating ${type}, falling back to API: ${result.error}`)
298// Fall back to API
299}
300} catch (error) {
301console.error("CLI error, falling back to API:", getErrorMessage(error))
302// Fall back to API on error
303}
304}
305306// API implementation (original code)
307try {
308let queryParams = `?path=${encodeURIComponent(filePath)}`
316}
317318const data = await callValTownApi(
319config,
320`/v2/vals/${valId}/files${queryParams}`,
384}
385} else {
386console.error(`CLI error when updating file, falling back to API: ${result.error}`)
387// Fall back to API
388}
389} catch (error) {
390console.error("CLI error, falling back to API:", getErrorMessage(error))
391// Fall back to API on error
392}
393}
394395// API implementation (original code)
396try {
397let queryParams = `?path=${encodeURIComponent(filePath)}`
400}
401402const data = await callValTownApi(
403config,
404`/v2/vals/${valId}/files${queryParams}`,
488}
489} else {
490console.error(`CLI error when deleting path, falling back to API: ${result.error}`)
491// Fall back to API
492}
493} catch (error) {
494console.error("CLI error, falling back to API:", getErrorMessage(error))
495// Fall back to API on error
496}
497}
498499// API implementation (original code)
500try {
501let queryParams = `?path=${encodeURIComponent(filePath)}&recursive=${recursive}`
504}
505506await callValTownApi(
507config,
508`/v2/vals/${valId}/files${queryParams}`,
val-town-http-mcp-serveruserTools.ts3 matches
2import {z} from "zod"
3import {Config} from "../lib/types.ts"
4import {callValTownApi} from "../lib/api.ts"
5import {getErrorMessage} from "../lib/errorUtils.ts"
615async ({username}: {username: string}) => {
16try {
17const data = await callValTownApi(config, `/v1/alias/${encodeURIComponent(username)}`)
1819return {
37async () => {
38try {
39const data = await callValTownApi(config, "/v1/me")
4041return {
val-town-http-mcp-serverblobTools.ts9 matches
2import {z} from "zod"
3import {Config} from "../lib/types.ts"
4import {callValTownApi} from "../lib/api.ts"
5import {getErrorMessage} from "../lib/errorUtils.ts"
616try {
17const queryParams = prefix ? `?prefix=${encodeURIComponent(prefix)}` : ""
18const data = await callValTownApi(config, `/v1/blob${queryParams}`)
1920return {
41try {
42// For blobs, we need to handle binary data differently
43const url = `${config.apiBase}/v1/blob/${encodeURIComponent(key)}`
44const response = await fetch(url, {
45headers: {
46"Authorization": `Bearer ${config.apiToken}`,
47},
48})
50if (!response.ok) {
51const errorText = await response.text()
52throw new Error(`API request failed: ${response.status} ${response.statusText}\n${errorText}`)
53}
54109}
110111const url = `${config.apiBase}/v1/blob/${encodeURIComponent(key)}`
112const response = await fetch(url, {
113method: "POST",
114headers: {
115"Authorization": `Bearer ${config.apiToken}`,
116"Content-Type": contentType,
117},
121if (!response.ok) {
122const errorText = await response.text()
123throw new Error(`API request failed: ${response.status} ${response.statusText}\n${errorText}`)
124}
125146async ({key}: {key: string}) => {
147try {
148await callValTownApi(config, `/v1/blob/${encodeURIComponent(key)}`, {
149method: "DELETE",
150})
2import {z} from "zod"
3import {Config} from "../lib/types.ts"
4import {callValTownApi} from "../lib/api.ts"
5import {getCliAvailability, runVtCommand} from "../lib/vtCli.ts"
616async ({limit, offset}: {limit: number; offset: number}) => {
17try {
18const data = await callValTownApi(
19config,
20`/v1/me/projects?limit=${limit}&offset=${offset}`
44async ({projectId}: {projectId: string}) => {
45try {
46const data = await callValTownApi(config, `/v1/projects/${projectId}`)
4748return {
84}
85}
86// If CLI fails, fall back to API
87} catch (error) {
88console.error("CLI error:", error)
89// Continue to API fallback
90}
91}
9293// Fallback to original API implementation
94try {
95const data = await callValTownApi(
96config,
97`/v1/alias/projects/${encodeURIComponent(username)}/${encodeURIComponent(projectName)}`
162}
163164const data = await callValTownApi(config, "/v1/projects", {
165method: "POST",
166body: JSON.stringify(payload),
190async ({projectId}: {projectId: string}) => {
191try {
192await callValTownApi(config, `/v1/projects/${projectId}`, {
193method: "DELETE",
194})
val-town-http-mcp-server.env.example2 matches
1# Val Town API token - get from https://www.val.town/settings
2VAL_TOWN_API_TOKEN=your_api_token_here
3