Skip to content

Commit d75da06

Browse files
authored
feat: mcp-ts (#19)
* feat: mcp-ts * chore: adjust folder name * chore: update Dockerfile * chore: update README.md * fix: adjust Dockerfile from express base to nodejs base
1 parent a655e32 commit d75da06

File tree

11 files changed

+1830
-1
lines changed

11 files changed

+1830
-1
lines changed

Service/mcp/typescript-1-8/Dockerfile

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
FROM ghcr.io/labring-actions/devbox/debian-ssh-12.6:547a61
2+
3+
USER root
4+
RUN cd /home/devbox/project && \
5+
rm -rf ./*
6+
7+
USER devbox
8+
ENV NODE_VERSION 22
9+
ENV NVM_DIR /home/devbox/.nvm
10+
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash \
11+
&& . $NVM_DIR/nvm.sh
12+
13+
USER root
14+
COPY /Service/mcp/typescript-1-8/project /home/devbox/project
15+
16+
RUN apt-get update && \
17+
apt-get install -y curl && \
18+
curl -sL https://deb.nodesource.com/setup_22.x | bash - && \
19+
apt-get install -y nodejs && \
20+
npm install -g typescript yarn pnpm && \
21+
apt-get clean && \
22+
rm -rf /var/lib/apt/lists/* && \
23+
chown -R devbox:devbox /home/devbox/project && \
24+
chmod -R u+rw /home/devbox/project && \
25+
chmod -R +x /home/devbox/project/entrypoint.sh
26+
27+
USER devbox
28+
RUN cd /home/devbox/project && \
29+
npm install
30+
31+
RUN mkdir -p /home/devbox/.devbox
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
node_modules
2+
dist
3+
.env
4+
.DS_Store
5+
npm-debug.log*
6+
yarn-debug.log*
7+
yarn-error.log*
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"recommendations": [
3+
"pomdtr.excalidraw-editor",
4+
"editorconfig.editorconfig",
5+
"lokalise.i18n-ally",
6+
"esbenp.prettier-vscode",
7+
"dbaeumer.vscode-eslint",
8+
"burkeholland.simple-react-snippets",
9+
"prisma.prisma",
10+
"bradlc.vscode-tailwindcss"
11+
]
12+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# TypeScript MCP Server Example
2+
3+
This is a simple TypeScript web server application example that demonstrates Model Context Protocol (MCP) server functionality.
4+
5+
### How to develop
6+
7+
1. Run `bash entrypoint.sh`, this will start the TypeScript server in development mode with hot-reloading and launch the MCP inspector for debugging.
8+
> Note: You can also run `npm run dev` to start the server and MCP inspector.
9+
2. Your MCP server will be running on [localhost:3001](http://localhost:3001)
10+
3. Open the MCP inspector in [localhost:5173](http://localhost:5173)
11+
12+
## Project Description
13+
14+
This project creates a lightweight MCP server using TypeScript and Express.js. The server implements the Model Context Protocol (v1.8.0) and provides a development environment with integrated debugging capabilities. The project supports both development and production environment modes with proper TypeScript compilation and execution.
15+
16+
## Environment
17+
18+
This project runs on a Node.js environment with TypeScript development tools, which are pre-configured in the Devbox environment. You don't need to worry about setting up TypeScript compiler or system dependencies yourself. The development environment includes all necessary tools for building and running TypeScript applications. If you need to make adjustments to match your specific requirements, you can modify the configuration files accordingly.
19+
20+
## Project Execution
21+
22+
**Development mode:** For normal development environment, simply enter Devbox and run `bash entrypoint.sh` in the terminal. This will start the TypeScript server in development mode with hot-reloading and launch the MCP inspector for debugging.
23+
24+
**Production mode:** After release, the project will be automatically packaged into a Docker image and deployed according to the `entrypoint.sh` script with production parameters (run `bash entrypoint.sh production`). This will build an optimized JavaScript bundle and run it.
25+
26+
DevBox: Code. Build. Deploy. We've Got the Rest.
27+
With DevBox, you can focus entirely on writing great code while we handle the infrastructure, scaling, and deployment. Seamless development from start to production.
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
import { z } from 'zod'
2+
import express, { Request, Response } from 'express'
3+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
4+
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js'
5+
6+
interface ToolResult {
7+
[key: string]: unknown
8+
content: Array<{
9+
type: 'text'
10+
text: string
11+
}>
12+
isError?: boolean
13+
}
14+
15+
interface PromptResult {
16+
[key: string]: unknown
17+
messages: Array<{
18+
role: 'user' | 'assistant'
19+
content: {
20+
type: 'text'
21+
text: string
22+
}
23+
}>
24+
}
25+
26+
const server = new McpServer({
27+
name: 'mcp-sse-server',
28+
version: '1.0.0',
29+
})
30+
31+
const textResource = {
32+
name: 'text-example',
33+
uri: 'resource://text-example',
34+
async callback() {
35+
return {
36+
contents: [
37+
{
38+
uri: 'resource://text-example',
39+
text: 'Hello, MCP!',
40+
},
41+
],
42+
}
43+
},
44+
}
45+
46+
server.resource(textResource.name, textResource.uri, textResource.callback)
47+
48+
const calculateTool = {
49+
name: 'calculate',
50+
description: 'Calculate the result of the expression',
51+
parameters: {
52+
expression: z.string().describe('The mathematical expression to calculate'),
53+
},
54+
async handler(extra: any): Promise<ToolResult> {
55+
try {
56+
const result = Function(`'use strict'; return (${extra.expression})`)()
57+
return {
58+
content: [
59+
{
60+
type: 'text',
61+
text: String(result),
62+
},
63+
],
64+
}
65+
} catch (error: any) {
66+
return {
67+
content: [
68+
{
69+
type: 'text',
70+
text: `Calculation error: ${error.message}`,
71+
},
72+
],
73+
isError: true,
74+
}
75+
}
76+
},
77+
}
78+
79+
server.tool(
80+
calculateTool.name,
81+
calculateTool.description,
82+
calculateTool.parameters,
83+
calculateTool.handler
84+
)
85+
86+
const codeAnalysisPrompt = {
87+
name: 'analyze-code',
88+
description: 'Analyze code and provide improvement suggestions',
89+
arguments: {
90+
language: z.string().describe('Programming language'),
91+
code: z.string().describe('Code to analyze'),
92+
},
93+
async getMessages(extra: any): Promise<PromptResult> {
94+
return {
95+
messages: [
96+
{
97+
role: 'user',
98+
content: {
99+
type: 'text',
100+
text: `Please analyze the following ${
101+
extra.language || 'unspecified'
102+
} code and provide improvement suggestions:\n\n\`\`\`${
103+
extra.language
104+
}\n${extra.code}\n\`\`\``,
105+
},
106+
},
107+
],
108+
}
109+
},
110+
}
111+
112+
server.prompt(
113+
codeAnalysisPrompt.name,
114+
codeAnalysisPrompt.description,
115+
codeAnalysisPrompt.arguments,
116+
codeAnalysisPrompt.getMessages
117+
)
118+
119+
const app = express()
120+
121+
const transports: { [sessionId: string]: SSEServerTransport } = {}
122+
123+
app.get('/sse', async (_: Request, res: Response) => {
124+
const transport = new SSEServerTransport('/messages', res)
125+
transports[transport.sessionId] = transport
126+
127+
res.on('close', () => {
128+
delete transports[transport.sessionId]
129+
})
130+
131+
await server.connect(transport)
132+
})
133+
134+
app.post('/messages', async (req: Request, res: Response) => {
135+
const sessionId = req.query.sessionId as string
136+
const transport = transports[sessionId]
137+
138+
if (transport) {
139+
await transport.handlePostMessage(req, res)
140+
} else {
141+
res.status(400).send('not found')
142+
}
143+
})
144+
145+
const PORT = process.env.PORT || 3001
146+
app.listen(PORT, () => {
147+
console.log(`MCP SSE Running at http://localhost:${PORT}`)
148+
})
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#!/bin/bash
2+
3+
app_env=${1:-development}
4+
5+
# Development environment commands
6+
dev_commands() {
7+
echo "Running Express.js development environment..."
8+
# Install development dependencies if they're not already installed
9+
npm install
10+
11+
# Start the inspector and the server
12+
npm run dev
13+
}
14+
15+
# Production environment commands
16+
prod_commands() {
17+
echo "Running Express.js production environment..."
18+
# Install only production dependencies
19+
npm install --production
20+
# Start Express in production mode
21+
npm start
22+
}
23+
24+
# Check environment variables to determine the running environment
25+
if [ "$app_env" = "production" ] || [ "$app_env" = "prod" ] ; then
26+
echo "Production environment detected"
27+
prod_commands
28+
else
29+
echo "Development environment detected"
30+
dev_commands
31+
fi

0 commit comments

Comments
 (0)