();
158 |
159 | app.get("/sse", async (req, res) => {
160 | const id = Date.now().toString();
161 | const transport = new SSEServerTransport("/messages", res);
162 |
163 | activeTransports.set(id, transport);
164 |
165 | // Set headers for SSE
166 | res.setHeader('Content-Type', 'text/event-stream');
167 | res.setHeader('Cache-Control', 'no-cache');
168 | res.setHeader('Connection', 'keep-alive');
169 |
170 | // Handle client disconnect
171 | req.on('close', () => {
172 | activeTransports.delete(id);
173 | });
174 |
175 | await server.connect(transport);
176 | });
177 |
178 | app.post("/messages", express.json(), (req, res) => {
179 | // Get the last transport - in a production app, you'd want to maintain sessions
180 | const lastTransportId = Array.from(activeTransports.keys()).pop();
181 |
182 | if (!lastTransportId) {
183 | res.status(400).json({ error: "No active connections" });
184 | return;
185 | }
186 |
187 | const transport = activeTransports.get(lastTransportId);
188 | transport.handlePostMessage(req, res).catch((error: Error) => {
189 | console.error("Error handling message:", error);
190 | if (!res.headersSent) {
191 | res.status(500).json({ error: "Internal server error" });
192 | }
193 | });
194 | });
195 |
196 | // Simple home page
197 | app.get("/", (req, res) => {
198 | res.send(`
199 |
200 |
201 | ServeMyAPI
202 |
208 |
209 |
210 | ServeMyAPI
211 | This is a personal MCP server for securely storing and accessing API keys across projects using the macOS Keychain.
212 | The server exposes the following tools:
213 |
214 | - store-api-key - Store an API key in the keychain
215 | - get-api-key - Retrieve an API key from the keychain
216 | - delete-api-key - Delete an API key from the keychain
217 | - list-api-keys - List all stored API keys
218 |
219 | This server is running with HTTP SSE transport. Connect to /sse for the SSE endpoint and post messages to /messages.
220 |
221 |
222 | `);
223 | });
224 |
225 | // Start the server
226 | app.listen(port, () => {
227 | console.log(`ServeMyAPI HTTP server is running on port ${port}`);
228 | });
229 |
230 | export { server };
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ServeMyAPI
2 |
3 | [](https://smithery.ai/server/@Jktfe/servemyapi)
4 |
5 | A personal MCP (Model Context Protocol) server for securely storing and accessing API keys across projects using the macOS Keychain.
6 |
7 | > **IMPORTANT**: ServeMyAPI is a macOS-specific tool that relies on the macOS Keychain for secure storage. It is not compatible with Windows or Linux operating systems. See the security notes section for more details.
8 |
9 | ## Overview
10 |
11 | ServeMyAPI allows you to store API keys securely in the macOS Keychain and access them through a consistent MCP interface. This makes it easy to:
12 |
13 | - Store API keys securely (they're never visible in .env files or config files)
14 | - Access the same keys across multiple projects
15 | - Use natural language to store and retrieve keys (when used with LLMs like Claude)
16 | - Provide keys directly to your AI assistant when it needs to access services
17 |
18 | ## Why ServeMyAPI over .ENV Files?
19 |
20 | Using ServeMyAPI instead of traditional .ENV files solves several common problems:
21 |
22 | 1. **GitHub Security Conflicts**:
23 | - .ENV files need to be excluded from Git repositories for security (via .gitignore)
24 | - This creates a "hidden context" problem where important configuration is invisible to collaborators and LLMs
25 | - New developers often struggle with setting up the correct environment variables
26 |
27 | 2. **LLM Integration Challenges**:
28 | - LLMs like Claude can't directly access your .ENV files due to security constraints
29 | - When LLMs need API keys to complete tasks, you often need manual workarounds
30 | - ServeMyAPI lets your AI assistant request keys through natural language
31 |
32 | 3. **Cross-Project Consistency**:
33 | - With .ENV files, you typically need to duplicate API keys across multiple projects
34 | - When keys change, you need to update multiple files
35 | - ServeMyAPI provides a central storage location accessible from any project
36 |
37 | This approach gives you the best of both worlds: secure storage of sensitive credentials without sacrificing visibility and accessibility for your AI tools.
38 |
39 | ## Features
40 |
41 | - Secure storage of API keys in the macOS Keychain
42 | - Simple MCP tools for storing, retrieving, listing, and deleting keys
43 | - Convenient CLI interface for terminal-based key management
44 | - Support for both stdio and HTTP/SSE transports
45 | - Compatible with any MCP client (Claude Desktop, etc.)
46 |
47 | ## Installation
48 |
49 | ```bash
50 | # Clone the repository
51 | git clone https://github.com/yourusername/servemyapi.git
52 | cd servemyapi
53 |
54 | # Install dependencies
55 | npm install
56 |
57 | # Build the project
58 | npm run build
59 | ```
60 |
61 | ## Usage
62 |
63 | ### CLI Interface
64 |
65 | ServeMyAPI comes with a command-line interface for quick key management directly from your terminal:
66 |
67 | ```bash
68 | # Install the CLI globally
69 | npm run build
70 | npm link
71 |
72 | # List all stored API keys
73 | api-key list
74 |
75 | # Get a specific API key
76 | api-key get github_token
77 |
78 | # Store a new API key
79 | api-key store github_token ghp_123456789abcdefg
80 |
81 | # Delete an API key
82 | api-key delete github_token
83 |
84 | # Display help
85 | api-key help
86 | ```
87 |
88 | ### Running as a stdio server
89 |
90 | This is the simplest way to use ServeMyAPI as an MCP server, especially when working with Claude Desktop:
91 |
92 | ```bash
93 | npm start
94 | ```
95 |
96 | ### Running as an HTTP server
97 |
98 | For applications that require HTTP access:
99 |
100 | ```bash
101 | node dist/server.js
102 | ```
103 |
104 | This will start the server on port 3000 (or the port specified in the PORT environment variable).
105 |
106 | ### Using Smithery
107 |
108 | ServeMyAPI is available as a hosted service on [Smithery](https://smithery.ai/server/@Jktfe/servemyapi).
109 |
110 | ```javascript
111 | import { createTransport } from "@smithery/sdk/transport.js"
112 |
113 | const transport = createTransport("https://server.smithery.ai/@Jktfe/servemyapi")
114 |
115 | // Create MCP client
116 | import { Client } from "@modelcontextprotocol/sdk/client/index.js"
117 |
118 | const client = new Client({
119 | name: "Test client",
120 | version: "1.0.0"
121 | })
122 | await client.connect(transport)
123 |
124 | // Use the server tools with your LLM application
125 | const tools = await client.listTools()
126 | console.log(`Available tools: ${tools.map(t => t.name).join(", ")}`)
127 | ```
128 |
129 | For more details, see the [Smithery API documentation](https://smithery.ai/server/@Jktfe/servemyapi/api).
130 |
131 | ### Configuring MCP Clients
132 |
133 | ServeMyAPI works with any MCP-compatible client. Example configuration files are provided in the `examples` directory.
134 |
135 | #### Claude Desktop
136 |
137 | To use ServeMyAPI with Claude Desktop:
138 |
139 | 1. Locate or create the Claude Desktop configuration file:
140 | - **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
141 | - **Windows**: `%AppData%\Claude\claude_desktop_config.json`
142 |
143 | 2. Add ServeMyAPI to the `mcpServers` section (you can copy from `examples/claude_desktop_config.json`):
144 | ```json
145 | {
146 | "mcpServers": {
147 | "serveMyAPI": {
148 | "command": "node",
149 | "args": [
150 | "/ABSOLUTE/PATH/TO/servemyapi/dist/index.js"
151 | ]
152 | }
153 | }
154 | }
155 | ```
156 |
157 | 3. Replace `/ABSOLUTE/PATH/TO/servemyapi` with the actual path to your ServeMyAPI installation.
158 | 4. Restart Claude Desktop.
159 |
160 | #### Windsurf
161 |
162 | To use ServeMyAPI with Windsurf:
163 |
164 | 1. Open Windsurf editor and navigate to Settings
165 | 2. Add ServeMyAPI to your MCP server configuration using the example in `examples/windsurf_config.json`
166 | 3. Adapt the paths to your local installation
167 |
168 | ## MCP Tools
169 |
170 | ServeMyAPI exposes the following tools:
171 |
172 | ### store-api-key
173 |
174 | Store an API key in the keychain.
175 |
176 | Parameters:
177 | - `name`: The name/identifier for the API key
178 | - `key`: The API key to store
179 |
180 | Example (from Claude):
181 | ```
182 | Using serveMyAPI, store my API key ABC123XYZ as "OpenAI API Key"
183 | ```
184 |
185 | ### get-api-key
186 |
187 | Retrieve an API key from the keychain.
188 |
189 | Parameters:
190 | - `name`: The name/identifier of the API key to retrieve
191 |
192 | Example (from Claude):
193 | ```
194 | Using serveMyAPI, get the API key named "OpenAI API Key"
195 | ```
196 |
197 | ### delete-api-key
198 |
199 | Delete an API key from the keychain.
200 |
201 | Parameters:
202 | - `name`: The name/identifier of the API key to delete
203 |
204 | Example (from Claude):
205 | ```
206 | Using serveMyAPI, delete the API key named "OpenAI API Key"
207 | ```
208 |
209 | ### list-api-keys
210 |
211 | List all stored API keys.
212 |
213 | No parameters required.
214 |
215 | Example (from Claude):
216 | ```
217 | Using serveMyAPI, list all my stored API keys
218 | ```
219 |
220 | ## Security Notes
221 |
222 | - All API keys are stored securely in the macOS Keychain
223 | - Keys are only accessible to the current user
224 | - The keychain requires authentication for access
225 | - No keys are stored in plaintext or logged anywhere
226 |
227 | ## Roadmap
228 |
229 | Future plans for ServeMyAPI include:
230 |
231 | - **Code Scanner Tool**: A tool that automatically scans your codebase for API endpoints, sensitive URLs, and environment variables, then suggests names to store them in the Keychain. This would allow developers to continue using .ENV files in their regular workflow while ensuring credentials are also available to LLMs and other tools when needed.
232 |
233 | - **Cross-Platform Support**: Investigating secure credential storage options for Windows and Linux to make ServeMyAPI more widely accessible.
234 |
235 | - **Integration with Popular Frameworks**: Providing easy integration with frameworks like Next.js, Express, and others.
236 |
237 | - **UI for Key Management**: A simple web interface for managing your stored API keys directly.
238 |
239 | Feel free to suggest additional features or contribute to the roadmap by opening an issue or pull request.
240 |
241 | ## Development
242 |
243 | ```bash
244 | # Run in development mode with hot reload
245 | npm run dev
246 |
247 | # Use the CLI during development
248 | npm run cli list
249 |
250 | # Lint the code
251 | npm run lint
252 |
253 | # Build for production
254 | npm run build
255 | ```
256 |
257 | ## License
258 |
259 | MIT
--------------------------------------------------------------------------------
/MCP-TypeScript-Readme.md:
--------------------------------------------------------------------------------
1 | # MCP TypeScript SDK  
2 |
3 | ## Table of Contents
4 | - [Overview](#overview)
5 | - [Installation](#installation)
6 | - [Quickstart](#quickstart)
7 | - [What is MCP?](#what-is-mcp)
8 | - [Core Concepts](#core-concepts)
9 | - [Server](#server)
10 | - [Resources](#resources)
11 | - [Tools](#tools)
12 | - [Prompts](#prompts)
13 | - [Running Your Server](#running-your-server)
14 | - [stdio](#stdio)
15 | - [HTTP with SSE](#http-with-sse)
16 | - [Testing and Debugging](#testing-and-debugging)
17 | - [Examples](#examples)
18 | - [Echo Server](#echo-server)
19 | - [SQLite Explorer](#sqlite-explorer)
20 | - [Advanced Usage](#advanced-usage)
21 | - [Low-Level Server](#low-level-server)
22 | - [Writing MCP Clients](#writing-mcp-clients)
23 | - [Server Capabilities](#server-capabilities)
24 |
25 | ## Overview
26 |
27 | The Model Context Protocol allows applications to provide context for LLMs in a standardized way, separating the concerns of providing context from the actual LLM interaction. This TypeScript SDK implements the full MCP specification, making it easy to:
28 |
29 | - Build MCP clients that can connect to any MCP server
30 | - Create MCP servers that expose resources, prompts and tools
31 | - Use standard transports like stdio and SSE
32 | - Handle all MCP protocol messages and lifecycle events
33 |
34 | ## Installation
35 |
36 | ```bash
37 | npm install @modelcontextprotocol/sdk
38 | ```
39 |
40 | ## Quick Start
41 |
42 | Let's create a simple MCP server that exposes a calculator tool and some data:
43 |
44 | ```typescript
45 | import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
46 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
47 | import { z } from "zod";
48 |
49 | // Create an MCP server
50 | const server = new McpServer({
51 | name: "Demo",
52 | version: "1.0.0"
53 | });
54 |
55 | // Add an addition tool
56 | server.tool("add",
57 | { a: z.number(), b: z.number() },
58 | async ({ a, b }) => ({
59 | content: [{ type: "text", text: String(a + b) }]
60 | })
61 | );
62 |
63 | // Add a dynamic greeting resource
64 | server.resource(
65 | "greeting",
66 | new ResourceTemplate("greeting://{name}", { list: undefined }),
67 | async (uri, { name }) => ({
68 | contents: [{
69 | uri: uri.href,
70 | text: `Hello, ${name}!`
71 | }]
72 | })
73 | );
74 |
75 | // Start receiving messages on stdin and sending messages on stdout
76 | const transport = new StdioServerTransport();
77 | await server.connect(transport);
78 | ```
79 |
80 | ## What is MCP?
81 |
82 | The [Model Context Protocol (MCP)](https://modelcontextprotocol.io) lets you build servers that expose data and functionality to LLM applications in a secure, standardized way. Think of it like a web API, but specifically designed for LLM interactions. MCP servers can:
83 |
84 | - Expose data through **Resources** (think of these sort of like GET endpoints; they are used to load information into the LLM's context)
85 | - Provide functionality through **Tools** (sort of like POST endpoints; they are used to execute code or otherwise produce a side effect)
86 | - Define interaction patterns through **Prompts** (reusable templates for LLM interactions)
87 | - And more!
88 |
89 | ## Core Concepts
90 |
91 | ### Server
92 |
93 | The McpServer is your core interface to the MCP protocol. It handles connection management, protocol compliance, and message routing:
94 |
95 | ```typescript
96 | const server = new McpServer({
97 | name: "My App",
98 | version: "1.0.0"
99 | });
100 | ```
101 |
102 | ### Resources
103 |
104 | Resources are how you expose data to LLMs. They're similar to GET endpoints in a REST API - they provide data but shouldn't perform significant computation or have side effects:
105 |
106 | ```typescript
107 | // Static resource
108 | server.resource(
109 | "config",
110 | "config://app",
111 | async (uri) => ({
112 | contents: [{
113 | uri: uri.href,
114 | text: "App configuration here"
115 | }]
116 | })
117 | );
118 |
119 | // Dynamic resource with parameters
120 | server.resource(
121 | "user-profile",
122 | new ResourceTemplate("users://{userId}/profile", { list: undefined }),
123 | async (uri, { userId }) => ({
124 | contents: [{
125 | uri: uri.href,
126 | text: `Profile data for user ${userId}`
127 | }]
128 | })
129 | );
130 | ```
131 |
132 | ### Tools
133 |
134 | Tools let LLMs take actions through your server. Unlike resources, tools are expected to perform computation and have side effects:
135 |
136 | ```typescript
137 | // Simple tool with parameters
138 | server.tool(
139 | "calculate-bmi",
140 | {
141 | weightKg: z.number(),
142 | heightM: z.number()
143 | },
144 | async ({ weightKg, heightM }) => ({
145 | content: [{
146 | type: "text",
147 | text: String(weightKg / (heightM * heightM))
148 | }]
149 | })
150 | );
151 |
152 | // Async tool with external API call
153 | server.tool(
154 | "fetch-weather",
155 | { city: z.string() },
156 | async ({ city }) => {
157 | const response = await fetch(`https://api.weather.com/${city}`);
158 | const data = await response.text();
159 | return {
160 | content: [{ type: "text", text: data }]
161 | };
162 | }
163 | );
164 | ```
165 |
166 | ### Prompts
167 |
168 | Prompts are reusable templates that help LLMs interact with your server effectively:
169 |
170 | ```typescript
171 | server.prompt(
172 | "review-code",
173 | { code: z.string() },
174 | ({ code }) => ({
175 | messages: [{
176 | role: "user",
177 | content: {
178 | type: "text",
179 | text: `Please review this code:\n\n${code}`
180 | }
181 | }]
182 | })
183 | );
184 | ```
185 |
186 | ## Running Your Server
187 |
188 | MCP servers in TypeScript need to be connected to a transport to communicate with clients. How you start the server depends on the choice of transport:
189 |
190 | ### stdio
191 |
192 | For command-line tools and direct integrations:
193 |
194 | ```typescript
195 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
196 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
197 |
198 | const server = new McpServer({
199 | name: "example-server",
200 | version: "1.0.0"
201 | });
202 |
203 | // ... set up server resources, tools, and prompts ...
204 |
205 | const transport = new StdioServerTransport();
206 | await server.connect(transport);
207 | ```
208 |
209 | ### HTTP with SSE
210 |
211 | For remote servers, start a web server with a Server-Sent Events (SSE) endpoint, and a separate endpoint for the client to send its messages to:
212 |
213 | ```typescript
214 | import express from "express";
215 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
216 | import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
217 |
218 | const server = new McpServer({
219 | name: "example-server",
220 | version: "1.0.0"
221 | });
222 |
223 | // ... set up server resources, tools, and prompts ...
224 |
225 | const app = express();
226 |
227 | app.get("/sse", async (req, res) => {
228 | const transport = new SSEServerTransport("/messages", res);
229 | await server.connect(transport);
230 | });
231 |
232 | app.post("/messages", async (req, res) => {
233 | // Note: to support multiple simultaneous connections, these messages will
234 | // need to be routed to a specific matching transport. (This logic isn't
235 | // implemented here, for simplicity.)
236 | await transport.handlePostMessage(req, res);
237 | });
238 |
239 | app.listen(3001);
240 | ```
241 |
242 | ### Testing and Debugging
243 |
244 | To test your server, you can use the [MCP Inspector](https://github.com/modelcontextprotocol/inspector). See its README for more information.
245 |
246 | ## Examples
247 |
248 | ### Echo Server
249 |
250 | A simple server demonstrating resources, tools, and prompts:
251 |
252 | ```typescript
253 | import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
254 | import { z } from "zod";
255 |
256 | const server = new McpServer({
257 | name: "Echo",
258 | version: "1.0.0"
259 | });
260 |
261 | server.resource(
262 | "echo",
263 | new ResourceTemplate("echo://{message}", { list: undefined }),
264 | async (uri, { message }) => ({
265 | contents: [{
266 | uri: uri.href,
267 | text: `Resource echo: ${message}`
268 | }]
269 | })
270 | );
271 |
272 | server.tool(
273 | "echo",
274 | { message: z.string() },
275 | async ({ message }) => ({
276 | content: [{ type: "text", text: `Tool echo: ${message}` }]
277 | })
278 | );
279 |
280 | server.prompt(
281 | "echo",
282 | { message: z.string() },
283 | ({ message }) => ({
284 | messages: [{
285 | role: "user",
286 | content: {
287 | type: "text",
288 | text: `Please process this message: ${message}`
289 | }
290 | }]
291 | })
292 | );
293 | ```
294 |
295 | ### SQLite Explorer
296 |
297 | A more complex example showing database integration:
298 |
299 | ```typescript
300 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
301 | import sqlite3 from "sqlite3";
302 | import { promisify } from "util";
303 | import { z } from "zod";
304 |
305 | const server = new McpServer({
306 | name: "SQLite Explorer",
307 | version: "1.0.0"
308 | });
309 |
310 | // Helper to create DB connection
311 | const getDb = () => {
312 | const db = new sqlite3.Database("database.db");
313 | return {
314 | all: promisify(db.all.bind(db)),
315 | close: promisify(db.close.bind(db))
316 | };
317 | };
318 |
319 | server.resource(
320 | "schema",
321 | "schema://main",
322 | async (uri) => {
323 | const db = getDb();
324 | try {
325 | const tables = await db.all(
326 | "SELECT sql FROM sqlite_master WHERE type='table'"
327 | );
328 | return {
329 | contents: [{
330 | uri: uri.href,
331 | text: tables.map((t: {sql: string}) => t.sql).join("\n")
332 | }]
333 | };
334 | } finally {
335 | await db.close();
336 | }
337 | }
338 | );
339 |
340 | server.tool(
341 | "query",
342 | { sql: z.string() },
343 | async ({ sql }) => {
344 | const db = getDb();
345 | try {
346 | const results = await db.all(sql);
347 | return {
348 | content: [{
349 | type: "text",
350 | text: JSON.stringify(results, null, 2)
351 | }]
352 | };
353 | } catch (err: unknown) {
354 | const error = err as Error;
355 | return {
356 | content: [{
357 | type: "text",
358 | text: `Error: ${error.message}`
359 | }],
360 | isError: true
361 | };
362 | } finally {
363 | await db.close();
364 | }
365 | }
366 | );
367 | ```
368 |
369 | ## Advanced Usage
370 |
371 | ### Low-Level Server
372 |
373 | For more control, you can use the low-level Server class directly:
374 |
375 | ```typescript
376 | import { Server } from "@modelcontextprotocol/sdk/server/index.js";
377 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
378 | import {
379 | ListPromptsRequestSchema,
380 | GetPromptRequestSchema
381 | } from "@modelcontextprotocol/sdk/types.js";
382 |
383 | const server = new Server(
384 | {
385 | name: "example-server",
386 | version: "1.0.0"
387 | },
388 | {
389 | capabilities: {
390 | prompts: {}
391 | }
392 | }
393 | );
394 |
395 | server.setRequestHandler(ListPromptsRequestSchema, async () => {
396 | return {
397 | prompts: [{
398 | name: "example-prompt",
399 | description: "An example prompt template",
400 | arguments: [{
401 | name: "arg1",
402 | description: "Example argument",
403 | required: true
404 | }]
405 | }]
406 | };
407 | });
408 |
409 | server.setRequestHandler(GetPromptRequestSchema, async (request) => {
410 | if (request.params.name !== "example-prompt") {
411 | throw new Error("Unknown prompt");
412 | }
413 | return {
414 | description: "Example prompt",
415 | messages: [{
416 | role: "user",
417 | content: {
418 | type: "text",
419 | text: "Example prompt text"
420 | }
421 | }]
422 | };
423 | });
424 |
425 | const transport = new StdioServerTransport();
426 | await server.connect(transport);
427 | ```
428 |
429 | ### Writing MCP Clients
430 |
431 | The SDK provides a high-level client interface:
432 |
433 | ```typescript
434 | import { Client } from "@modelcontextprotocol/sdk/client/index.js";
435 | import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
436 |
437 | const transport = new StdioClientTransport({
438 | command: "node",
439 | args: ["server.js"]
440 | });
441 |
442 | const client = new Client(
443 | {
444 | name: "example-client",
445 | version: "1.0.0"
446 | },
447 | {
448 | capabilities: {
449 | prompts: {},
450 | resources: {},
451 | tools: {}
452 | }
453 | }
454 | );
455 |
456 | await client.connect(transport);
457 |
458 | // List prompts
459 | const prompts = await client.listPrompts();
460 |
461 | // Get a prompt
462 | const prompt = await client.getPrompt("example-prompt", {
463 | arg1: "value"
464 | });
465 |
466 | // List resources
467 | const resources = await client.listResources();
468 |
469 | // Read a resource
470 | const resource = await client.readResource("file:///example.txt");
471 |
472 | // Call a tool
473 | const result = await client.callTool({
474 | name: "example-tool",
475 | arguments: {
476 | arg1: "value"
477 | }
478 | });
479 | ```
480 |
481 | ## Documentation
482 |
483 | - [Model Context Protocol documentation](https://modelcontextprotocol.io)
484 | - [MCP Specification](https://spec.modelcontextprotocol.io)
485 | - [Example Servers](https://github.com/modelcontextprotocol/servers)
486 |
487 | ## Contributing
488 |
489 | Issues and pull requests are welcome on GitHub at https://github.com/modelcontextprotocol/typescript-sdk.
490 |
491 | ## License
492 |
493 | This project is licensed under the MIT License—see the [LICENSE](LICENSE) file for details.
--------------------------------------------------------------------------------
/CLAUDE.md:
--------------------------------------------------------------------------------
1 | # serveMyAPI Project Guide
2 |
3 | ## Project Purpose
4 | This project aims to create a personal MCP server for securely storing and accessing API keys across projects using the macOS Keychain.
5 |
6 | ## Build & Commands
7 | - Setup: `npm install`
8 | - Start server: `npm run dev`
9 | - Test: `npm test`
10 | - Lint: `npm run lint`
11 | - Build: `npm run build`
12 |
13 | ## Code Style Guidelines
14 | - **Formatting**: Follow TypeScript standard practices with 2-space indentation
15 | - **Imports**: Group imports by type (core, third-party, local)
16 | - **Naming**: Use camelCase for variables/functions, PascalCase for classes/interfaces
17 | - **Error Handling**: Use try/catch blocks for error management
18 | - **Security**: Never log or expose API keys in plaintext
19 | - **Documentation**: Document all public functions with JSDoc comments
20 |
21 | ## Key Technologies
22 | - TypeScript SDK for Model Context Protocol (MCP)
23 | - macOS Keychain API for secure credential storage
24 | - Express.js for API endpoints (if needed)
25 |
26 | # myAI Memory
27 |
28 | # General Response Style
29 | ## Use this in every response
30 | -~- You can be very concise
31 | -~- Always double check references and provide links to sources with validation of reference and trustworthy nature of the source, make use of the MCPs available
32 |
33 | # Personal Information
34 | ## User specific and personal information
35 | -~- Name: James William Peter King (James, JWPK)
36 | -~- Date of Birth: 29.03.1985 (40 years old)
37 | -~- Location: London, UK
38 | -~- Work Contact: james@newmodel.vc | 07793988228
39 | -~- Personal Contact: j.w.p.king@gmail.com | 07515900330
40 | -~- Family: Wife Roxanne (39), son Fletcher (8), daughter Viola (5) (pronounced Vi'la)
41 |
42 | ## Childhood & Education Background
43 | -~- Early Years: Grew up at Rendcomb boarding school in the Cotswolds where parents were housemasters
44 | -~- Primary Education: Cirencester County Juniors
45 | -~- Secondary Education:
46 | -~- Kimbolton School (GCSEs and French AS)
47 | -~- Leicester Grammar (3As, 2Bs at A-Level 2003)
48 | -~- Higher Education:
49 | -~- Imperial College (Computer Engineering first year)
50 | -~- Leeds University: BSc Computing (Scholarship) 2:1 (2005-2008)
51 | -~- Professional Qualifications: FCA Authorised principal
52 | -~- Learning Style: Quick to grasp concepts, excellent pattern recognition, quick to consider practical applications and implications
53 |
54 | ## Professional Background
55 | **Current Role**: CEO, Founder, and Director at New Model Venture Capital (NMVC, New Model)
56 | -~- Founded New Model in May 2013 to deliver "fast, intelligent capital to high-growth companies"
57 | -~- Developed investment products including the creation of the Guaranteed Venture Portfolio Loan (GVPL), which he raised £15.85m for as the first of its kind in the world
58 | **Previous Companies**:
59 | -~- Fig VC (Dec 2009-2023) - Founder
60 | -~- U Account (Jan-Jun 2019)
61 | -~- Wazoku (Jan 2011-Jun 2019) - Founder
62 | -~- Brightsparks (Oct 2012-Jul 2015)
63 | -~- MuJo (Jan 2011-Nov 2014) – Co-Founder
64 | -~- Students Work (Apr 2008-Dec 2009)
65 | -~- KPMG (Sep 2004-Aug 2005)
66 |
67 | ## Education
68 | -~- BSc Computing (Scholarship) 2:1 Leeds University (2005-2008)
69 | -~- FCA Authorised principal
70 | -~- Previous Education:
71 | -~- Leicester Grammar (3As, 2Bs at A-Level 2003)
72 | -~- Imperial College (Computer Engineering first year)
73 | -~- Kimbolton School (GCSEs and French AS)
74 |
75 | ## Key Achievements & Skills
76 | -~- Raised hundreds of millions in Debt and Equity
77 | -~- Delivered >30% IRR for past 15 years
78 | -~- Created Guaranteed Venture Portfolio Loan product, a new way of funding venture companies
79 | **Core Skills**: Financial Modelling, Deal structuring, Strategy development, Investment Analysis
80 | **Management Experience**: Teams up to 40 people, FCA MiFID compliance, professional qualification oversight
81 |
82 | ## Technical Expertise
83 | -~- Full-stack developer specializing in TypeScript, Svelte, and web technologies
84 | -~- Created GVPL Calculator - a sophisticated financial modelling platform
85 | -~- Developed myAImemory - AI memory synchronization tool
86 | -~- Built multiple Model Context Protocol (MCP) frameworks
87 | -~- Systems thinking and practical application to real-world problems
88 |
89 | # Personal Characteristics & Thinking Style
90 | -~- Excellent pattern recognition across different domains
91 | -~- Ability to see multiple perspectives ("windows") that others miss
92 | -~- Strong focus on fairness and equity in systems
93 | -~- Analytical approach to problems with multifaceted thinking
94 | -~- Quick to grasp concepts and translate complex ideas for others
95 | -~- Values transparency and documentation (always keen to see detailed records)
96 | -~- Draws clear boundaries when core principles are at stake
97 | -~- Weighs endurance/principles based on the significance of the issue
98 | -~- Willing to make personal sacrifices to establish precedents or prove concepts
99 | -~- Learning style: develops systematic approaches through direct observation, conversation and reading with a keen eye for evaluating the quality of sources
100 | -~- Incredibly quick to understand incentives and their implications
101 |
102 | # Interests
103 | -~- Rugby (qualified coach and referee)
104 | -~- Chess
105 | -~- Photography
106 | -~- Science and Technology
107 | -~- Snowboarding and Skiing
108 | -~- Golf
109 | -~- Guitar
110 | -~- Audiobooks and literature
111 | -~- Systems thinking and pattern recognition
112 | -~- His children and anything they do
113 |
114 | # Company Information
115 | **New Model Venture Capital**:
116 | -~- Mark Hanington (Managing Director)
117 | -~- James Stephenson (Head of Analysis)
118 | -~- Christian Fallesen (NED)
119 | -~- Keith Morris OBE (Advisor)
120 | -~- Matt Cunningham (Legal Counsel)
121 | -~- Team of 8 including legal, finance, and operations specialists
122 |
123 | ## Current Coding Projects
124 | -~- GVPL Calculator - Financial modelling platform for investment optimization
125 | -~- myAImemory - AI memory synchronization tool (Last modified: March 21, 2025)
126 | -~- myKYCpal - Know Your Client platform (Last modified: March 19, 2025)
127 | -~- serveMyAPI - API service for integrating with AI models
128 | -~- Multiple web applications using Svelte/TypeScript/Vercel/Neon including a Fantasy Rugby App
129 |
130 | # Technical Preferences
131 | ## Refer to this when considering examples and user experience testing
132 | -~- Frontend: Svelte 5
133 | -~- Development: Windsurf IDE
134 | -~- Hosting: Vercel
135 | -~- Database: Neon
136 | -~- Hardware: Mac Mini M4, MacBook Pro, iOS devices (iPhone 15 Pro, iPhone 16, iPad Pro)
137 | -~- Other devices: Apple TV, HomePod mini, HomePod, XReal One, GoPro 13 Hero Black, Nikon D50, Whoop fitness tracking
138 | -~- Visual Aids: uses visual explanations for complex concepts
139 |
140 | # AI & MCP Preferences
141 | ## Use this as a guide when working on technical projects
142 | -~- File Access: If a file is in .gitignore and need to read it, ask for permission to use the filesystem MCP
143 | -~- API credentials/services: Use the serveMyAPI MCP by @Jktfe
144 | -~- Response Style: Concise, UK English spelling, GBP (£) as default currency
145 | -~- Technical Documentation: Maintain "Project Variables" document with details on variables, functions, tables, etc.
146 | -~- AI Tools: Prefer Claude-based systems with pattern recognition capabilities
147 | -~- MCP Framework: Utilize multiple platform synchronization where possible
148 | -~- when creating an MCP it's important to add a proper MCP.js script with JSON-RPC handling
149 |
150 | # Communication Preferences
151 | -~- Respond in English
152 | -~- Use UK English Spellings
153 | -~- Use £ (GBP) as the default currency, if you need to use conversions put them in brackets i.e. £1.10 ($1.80)
154 | -~- Direct and straightforward communication
155 | -~- Appreciation for humour and casual conversation
156 | -~- Values authenticity over formality
157 | -~- Prefers evidence-based discussions
158 | -~- Open to new perspectives but requires logical reasoning
159 | -~- Expects transparency and honesty in professional relationships
160 | -~- Willing to challenge conventional wisdom when it doesn't align with practical outcomes
161 | -~- Respects expertise but will question assumptions that don't match observed reality
162 |
163 | # Available MCPs
164 | ## Use these details combined with serveMyAPI to create mcp config files
165 |
166 | ## Ask which servers to install, from this list;
167 |
168 | -~- "apple-shortcuts" - 1 tool: run_shortcut. Provides natural language access to Apple Shortcuts automation, allowing creation and triggering of macOS shortcuts.
169 |
170 | -~- "brave-search" - 2 tools: brave_web_search and brave_local_search. Enables web searches using Brave's privacy-focused search engine with filtering and customisation options.
171 |
172 | -~- "fastAPItoSVG" - 1 tool: generate_api_diagram. Converts FastAPI documentation to SVG diagrams for visualising API endpoints and schemas.
173 |
174 | -~- "fetch" - 1 tool: fetch. Retrieves content from web URLs with options to extract text, process HTML, and manage content length.
175 |
176 | -~- "filesystem" - 5 tools: ls, cat, write_file, rm, and mkdir. Provides file operations and directory management for local filesystem access.
177 |
178 | -~- "fooocus" - 9 tools: configure_api, check_status, start_server, stop_server, generate_image, get_job_status, get_available_styles, get_available_models, and upscale_or_vary_image. Interface to the Fooocus image generation AI with style presets, various models and upscaling options.
179 |
180 | -~- "google-search" - 1 tool: google_search. Performs web searches using Google's search engine with customisable parameters.
181 |
182 | -~- "localviz" - 6 tools: test_api, manage_api, list_styles, list_aspect_ratios, generate_image, and check_job_status. Local image generation interface for Fooocus with style presets and aspect ratio controls.
183 |
184 | -~- "leonardoAI" - 3 tools: generate_image, get_models, and check_generation. Creates AI-generated images with Leonardo.ai's advanced image generation capabilities.
185 |
186 | -~- "markdownify" - 1 tool: markdownify. Converts content between different formats with a focus on generating clean markdown.
187 |
188 | -~- "neon" - 11 tools: create_project, describe_project, list_projects, delete_project, create_branch, delete_branch, describe_branch, get_connection_string, get_database_tables, describe_table_schema, and run_sql. Manages Neon serverless PostgreSQL databases with branch, migration and query functionality.
189 |
190 | -~- "myai-memory-sync" - 8 tools: get_template, update_template, get_section, update_section, list_platforms, sync_platforms, list_presets, and create_preset. Synchronises and manages AI memory sections and templates across platforms.
191 |
192 | -~- "puppeteer" - 7 tools: navigate, screenshot, evaluate, click, fill, hover, and select. Automates browser interactions for web scraping, testing and automated workflows.
193 |
194 | -~- "sequential-thinking" - 1 tool: sequentialthinking. Facilitates step-by-step problem-solving through structured thought processes.
195 |
196 | -~- "serveMyAPI" - 4 tools: store-api-key, get-api-key, delete-api-key, and list-api-keys. Securely stores and retrieves API keys from the macOS Keychain for use across projects.
197 |
198 | -~- "wcgw" - 1 tool: analyze_code. "What Could Go Wrong" AI-powered code analysis for identifying potential issues and bugs.
199 |
200 | -~- "agentql" - 2 tools: create_agent and query_agent. Integrates with AgentQL to build and manage autonomous agents with various capabilities.
201 |
202 | -~- "mcp-compass" - 2 tools: get_coordinates and get_directions. Navigation and location-based services with mapping and direction capabilities.
203 |
204 | -~- "xcode-server" - 4 tools: list_projects, build_project, run_tests, and deploy_app. Interfaces with Xcode for iOS/macOS development workflows and build processes.
205 |
206 |
207 | ## once selected output the json with this format
208 | '''
209 | {
210 | "mcpServers": {
211 | [mcpserver details][,]
212 | }
213 | }
214 | '''
215 |
216 | # the individual mcp server details
217 |
218 | '''
219 | "fetch": {
220 | "command": "uvx",
221 | "args": [
222 | "mcp-server-fetch"
223 | ]
224 | }
225 | '''
226 |
227 | '''
228 | "filesystem": {
229 | "command": "npx",
230 | "args": [
231 | "-y",
232 | "@modelcontextprotocol/server-filesystem",
233 | "/Users/jamesking/"
234 | ]
235 | }
236 | '''
237 |
238 | '''
239 | "puppeteer": {
240 | "command": "npx",
241 | "args": [
242 | "-y",
243 | "@modelcontextprotocol/server-puppeteer"
244 | ]
245 | }
246 | '''
247 |
248 | '''
249 | "markdownify": {
250 | "command": "node",
251 | "args": [
252 | "/Users/jamesking/CascadeProjects/markdownify-mcp/dist/index.js"
253 | ],
254 | "env": {
255 | "UV_PATH": "/Users/jamesking/.local/bin/uv"
256 | }
257 | }
258 | '''
259 |
260 | '''
261 | "apple-shortcuts": {
262 | "command": "npx",
263 | "args": [
264 | "/Users/jamesking/CascadeProjects/mcp-server-apple-shortcuts/build/index.js"
265 | ]
266 | }
267 | '''
268 |
269 | '''
270 | "brave-search": {
271 | "command": "npx",
272 | "args": [
273 | "-y",
274 | "@modelcontextprotocol/server-brave-search"
275 | ],
276 | "env": {
277 | "BRAVE_API_KEY": "${await serveMyAPI.getKey('brave_search')}"
278 | }
279 | }
280 | '''
281 |
282 | '''
283 | "serveMyAPI": {
284 | "command": "node",
285 | "args": [
286 | "/Users/jamesking/CascadeProjects/serveMyAPI/dist/index.js"
287 | ]
288 | }
289 | '''
290 |
291 | '''
292 | "perplexity-ask": {
293 | "command": "docker",
294 | "args": [
295 | "run",
296 | "-i",
297 | "--rm",
298 | "-e",
299 | "PERPLEXITY_API_KEY",
300 | "mcp/perplexity-ask"
301 | ],
302 | "env": {
303 | "PERPLEXITY_API_KEY": "${await serveMyAPI.getKey('perplexity')}"
304 | }
305 | }
306 | '''
307 |
308 | '''
309 | "google-search": {
310 | "command": "npx",
311 | "args": [
312 | "-y",
313 | "@adenot/mcp-google-search"
314 | ],
315 | "env": {
316 | "GOOGLE_API_KEY": "${await serveMyAPI.getKey('google_search')}",
317 | "GOOGLE_SEARCH_ENGINE_ID": "${await serveMyAPI.getKey('google_search_engine_id')}"
318 | }
319 | }
320 | '''
321 |
322 | '''
323 | "myai-memory-sync": {
324 | "command": "node",
325 | "args": [
326 | "/Users/jamesking/CascadeProjects/myAImemory/dist/index.js"
327 | ],
328 | "transport":"stdio"
329 | }
330 | '''
331 |
332 | '''
333 | "neon": {
334 | "command": "npx",
335 | "args": [
336 | "-y",
337 | "@neondatabase/mcp-server-neon",
338 | "start",
339 | "${await serveMyAPI.getKey('neon_database')}"
340 | ]
341 | }
342 | '''
343 |
344 | '''
345 | "wcgw": {
346 | "command": "uv",
347 | "args": [
348 | "tool",
349 | "run",
350 | "--from",
351 | "wcgw@latest",
352 | "--python",
353 | "3.12",
354 | "wcgw_mcp"
355 | ]
356 | }
357 | '''
358 |
359 | '''
360 | "agentql": {
361 | "command": "npx",
362 | "args": [
363 | "-y",
364 | "agentql-mcp"
365 | ],
366 | "env": {
367 | "AGENTQL_API_KEY": "${await serveMyAPI.getKey('agentql')}"
368 | }
369 | }
370 | '''
371 |
372 | '''
373 | "mcp-compass": {
374 | "command": "npx",
375 | "args": [
376 | "-y",
377 | "@liuyoshio/mcp-compass"
378 | ]
379 | }
380 | '''
381 |
382 | '''
383 | "server-sequential-thinking": {
384 | "command": "npx",
385 | "args": [
386 | "-y",
387 | "@smithery/cli@latest",
388 | "run",
389 | "@smithery-ai/server-sequential-thinking",
390 | "--config",
391 | "\"{}\""
392 | ]
393 | }
394 | '''
395 |
396 | '''
397 | "fooocus": {
398 | "command": "bash",
399 | "args": [
400 | "/Users/jamesking/CascadeProjects/localViz/fooocus_mcp_wrapper.sh"
401 | ],
402 | "transport": "stdio",
403 | "functions": [
404 | {
405 | "name": "configure_api",
406 | "description": "Configure the Fooocus API connection settings with host, port, paths and auto-start options"
407 | },
408 | {
409 | "name": "check_status",
410 | "description": "Check if the Fooocus API is responding and get version information"
411 | },
412 | {
413 | "name": "start_server",
414 | "description": "Start the Fooocus API server if it's not already running, with optional paths"
415 | },
416 | {
417 | "name": "stop_server",
418 | "description": "Stop the Fooocus API server if it was started by this instance"
419 | },
420 | {
421 | "name": "generate_image",
422 | "description": "Generate images from text prompt using Fooocus with style, seed and resolution options"
423 | },
424 | {
425 | "name": "get_job_status",
426 | "description": "Get the status of a previously submitted asynchronous generation job"
427 | },
428 | {
429 | "name": "get_available_styles",
430 | "description": "Get all available style presets from Fooocus"
431 | },
432 | {
433 | "name": "get_available_models",
434 | "description": "Get all available AI models from Fooocus"
435 | },
436 | {
437 | "name": "upscale_or_vary_image",
438 | "description": "Upscale or create variations of an existing image with specified parameters"
439 | }
440 | ]
441 | }
442 | '''
443 |
444 | '''
445 | "localviz": {
446 | "command": "bash",
447 | "args": [
448 | "/Users/jamesking/CascadeProjects/localViz-mcp/start-v1.sh"
449 | ],
450 | "transport": "stdio",
451 | "env": {
452 | "FOOOCUS_API_PATH": "/Users/jamesking/CascadeProjects/Fooocus-API",
453 | "FOOOCUS_PATH": "/Users/jamesking/CascadeProjects/Fooocus",
454 | "OUTPUT_DIR": "/Users/jamesking/New Model Dropbox/James King/Air - JK Work/imageGens",
455 | "FOOOCUS_API_URL": "http://127.0.0.1:8888",
456 | "MANAGE_API": "true"
457 | },
458 | "functions": [
459 | {
460 | "name": "test_api",
461 | "description": "Test connection to the Fooocus API"
462 | },
463 | {
464 | "name": "manage_api",
465 | "description": "Manually start or stop the Fooocus API"
466 | },
467 | {
468 | "name": "list_styles",
469 | "description": "List all available style presets for image generation"
470 | },
471 | {
472 | "name": "list_aspect_ratios",
473 | "description": "List available aspect ratios for image generation"
474 | },
475 | {
476 | "name": "generate_image",
477 | "description": "Generate an image based on a text description using Fooocus API. Results will be saved locally."
478 | },
479 | {
480 | "name": "check_job_status",
481 | "description": "Check the status of an image generation job"
482 | }
483 | ]
484 | }
485 | '''
486 |
487 | '''
488 | "leonardoAI": {
489 | "command": "npm",
490 | "args": [
491 | "start"
492 | ],
493 | "cwd": "/Users/jamesking/CascadeProjects/leoViz",
494 | "transport": "stdio",
495 | "env": {
496 | "LEONARDO_API_KEY": "${await serveMyAPI.getKey('cMax Leonardo API')}"
497 | }
498 | }
499 | '''
--------------------------------------------------------------------------------