This package provides Model Context Protocol (MCP) server functionality for Theia, enabling AI tools to access Theia services and workspace information.
/mcp
e.g. http://localhost:3000/mcp
POST /mcp
- MCP protocol endpoint (for all MCP protocol operations)The MCP server architecture consists of:
Backend contributions run in the Node.js backend and have access to backend services:
@injectable()
export class MyBackendContribution implements MCPBackendContribution {
@inject(ILogger)
protected readonly logger: ILogger;
async configure(server: McpServer): Promise<void> {
// Register a tool
server.tool('my-backend-tool', {
type: 'object',
properties: {
input: { type: 'string' }
}
}, async (args) => {
this.logger.info('my-backend-tool called with args:', args);
return {
content: [{ type: 'text', text: 'Result from backend' }]
};
});
// Register a resource
server.resource(
'my-resource',
'theia://resource-uri',
async (uri) => {
return {
content: 'Resource content'
};
}
);
// Register a prompt
server.prompt(
'my-prompt',
'Prompt description',
{}, // Arguments schema
async (args) => {
return {
messages: [{
role: 'user',
content: { type: 'text', text: 'Prompt content' }
}]
};
}
);
}
}
Register the contribution in your backend module:
bind(MyBackendContribution).toSelf().inSingletonScope();
bind(MCPBackendContribution).toService(MyBackendContribution);
Frontend contributions run in the browser and have access to frontend services:
@injectable()
export class MyFrontendContribution implements MCPFrontendContribution {
@inject(WorkspaceService)
protected readonly workspaceService: WorkspaceService;
async getTools(): Promise<Tool[]> {
return [{
name: 'workspace-info',
description: 'Get workspace info',
inputSchema: {
type: 'object',
properties: {}
}
}];
}
async getTool(name: string): Promise<ToolProvider | undefined> {
if (name === 'workspace-info') {
return {
handler: async () => {
const roots = await this.workspaceService.roots;
return {
roots: roots.map(r => r.resource.toString())
};
},
inputSchema: z.object({})
};
}
}
async getResources(): Promise<Resource[]> {
return [{
name: 'Workspace Information',
uri: 'workspace://info',
description: 'Workspace info',
mimeType: 'application/json'
}];
}
async readResource(uri: string): Promise<unknown> {
if (uri === 'workspace://info') {
const roots = await this.workspaceService.roots;
return { roots: roots.map(r => r.resource.toString()) };
}
}
async getPrompts(): Promise<Prompt[]> {
return [{
name: 'workspace-context',
description: 'Generate workspace context',
arguments: []
}];
}
async getPrompt(name: string, args: unknown): Promise<PromptMessage[]> {
if (name === 'workspace-context') {
return [{
role: 'user',
content: { type: 'text', text: 'Workspace context information' }
}];
}
}
}
Register the contribution in your frontend module:
bind(MyFrontendContribution).toSelf().inSingletonScope();
bind(MCPFrontendContribution).toService(MyFrontendContribution);