Skip to main content
Glama
itsocialist

Claude Code Connector MCP

by itsocialist
index.ts7.39 kB
#!/usr/bin/env node /** * Claude Code Connector MCP Server * * Entry point for the MCP server that bridges Claude Desktop, * Claude Code CLI, and Claude Code for VS Code. */ import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema } from '@modelcontextprotocol/sdk/types.js'; import { RegisterProjectArgs, ListProjectsArgs, WriteToProjectArgs, ReadFromProjectArgs, MCPError } from './models/types.js'; import { registerProject } from './tools/register_project.js'; import { listProjects } from './tools/list_projects.js'; import { writeToProject } from './tools/write_to_project.js'; import { readFromProject } from './tools/read_from_project.js'; import { getProjectFilesResource } from './resources/project_files.js'; /** * Initialize the MCP server */ const server = new Server( { name: 'claude-code-connector', version: '0.1.0', }, { capabilities: { tools: {}, resources: {}, prompts: {}, }, } ); /** * Handler for listing available tools */ server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: 'register_project', description: 'Register a project directory for Claude Code Connector access', inputSchema: { type: 'object', properties: { name: { type: 'string', description: 'Human-readable project name' }, rootPath: { type: 'string', description: 'Absolute path to project root' }, id: { type: 'string', description: 'Optional unique ID (auto-generated if not provided)' }, specPaths: { type: 'array', items: { type: 'string' }, description: 'Relative paths for spec/doc storage' }, }, required: ['name', 'rootPath'], }, }, { name: 'list_projects', description: 'List all registered projects with status', inputSchema: { type: 'object', properties: { includeInactive: { type: 'boolean', description: 'Include inactive projects' } } } }, { name: 'write_to_project', description: 'Write content to a file in registered project directory', inputSchema: { type: 'object', properties: { projectId: { type: 'string', description: 'ID of registered project' }, filePath: { type: 'string', description: 'Relative path within project' }, content: { type: 'string', description: 'File content to write' }, createDirs: { type: 'boolean', description: 'Create parent directories if they don\'t exist' }, overwrite: { type: 'boolean', description: 'Overwrite if file exists' } }, required: ['projectId', 'filePath', 'content'] } }, { name: 'read_from_project', description: 'Read file content from registered project', inputSchema: { type: 'object', properties: { projectId: { type: 'string', description: 'ID of registered project' }, filePath: { type: 'string', description: 'Relative path within project' }, startLine: { type: 'number', description: 'Start reading from line N (1-indexed)' }, endLine: { type: 'number', description: 'Stop reading at line N (1-indexed)' } }, required: ['projectId', 'filePath'] } } ], }; }); /** * Handler for tool execution */ server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { switch (name) { case 'register_project': return { content: [{ type: 'text', text: JSON.stringify(await registerProject(args as unknown as RegisterProjectArgs), null, 2) }] }; case 'list_projects': return { content: [{ type: 'text', text: JSON.stringify(await listProjects(args as unknown as ListProjectsArgs), null, 2) }] }; case 'write_to_project': return { content: [{ type: 'text', text: JSON.stringify(await writeToProject(args as unknown as WriteToProjectArgs), null, 2) }] }; case 'read_from_project': return { content: [{ type: 'text', text: JSON.stringify(await readFromProject(args as unknown as ReadFromProjectArgs), null, 2) }] }; default: throw new Error(`Unknown tool: ${name}`); } } catch (error) { if (error instanceof MCPError) { return { content: [ { type: 'text', text: JSON.stringify({ error: error.code, message: error.message, suggestion: error.suggestion, }, null, 2), }, ], isError: true, }; } throw error; } }); /** * Handler for listing available resources */ server.setRequestHandler(ListResourcesRequestSchema, async () => { // In a real implementation this might be dynamic, but for now we rely on templates // or just listing what we know if possible? // Actually, resources are usually listed via templates or static list. // Spec says URI template: claude-code://{projectId}/files // We can list specific resources for *known* projects. // Import ProjectManager here to avoid top-level await issues? // Or just fetch inside. const { ProjectManager } = await import('./services/project_manager.js'); const pm = new ProjectManager(); const projects = await pm.getAllProjects(); return { resources: projects.map(p => ({ uri: `claude-code://${p.id}/files`, name: `${p.name} Files`, description: `Browserable file tree for ${p.name}`, mimeType: "application/json" })) }; }); /** * Handler for reading resources */ server.setRequestHandler(ReadResourceRequestSchema, async (request) => { const { uri } = request.params; // Parse URI: claude-code://{projectId}/files const match = uri.match(/^claude-code:\/\/([^\/]+)\/files$/); if (match) { const projectId = match[1]; try { const result = await getProjectFilesResource(projectId); return { contents: [{ uri, mimeType: "application/json", text: JSON.stringify(result, null, 2) }] }; } catch (error: any) { throw new Error(`Failed to read resource: ${error.message}`); } } throw new Error(`Resource not found: ${uri}`); }); /** * Handler for listing available prompts */ server.setRequestHandler(ListPromptsRequestSchema, async () => { return { prompts: [], }; }); /** * Handler for getting prompt content */ server.setRequestHandler(GetPromptRequestSchema, async (request) => { const { name } = request.params; throw new Error(`Prompt not found: ${name}`); }); /** * Start the server */ async function main() { const transport = new StdioServerTransport(); await server.connect(transport); console.error('Claude Code Connector MCP server running on stdio'); } main().catch((error) => { console.error('Fatal error in main():', error); process.exit(1); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/itsocialist/claude-code-connector-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server