Skip to content

Commit d00b095

Browse files
authored
feat: rest mode for storage server (#23)
1 parent 462d724 commit d00b095

File tree

19 files changed

+974
-64
lines changed

19 files changed

+974
-64
lines changed

Dockerfile

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,33 @@
1-
FROM node:20-alpine AS builder
1+
FROM node:22-alpine AS builder
22

3-
WORKDIR /app
3+
# Install pnpm
4+
RUN npm install -g pnpm
45

5-
# Copy package files
6-
COPY package.json pnpm-lock.yaml ./
6+
COPY ./ /app
77

8-
# Install dependencies
9-
RUN npm install -g pnpm && \
10-
pnpm install
8+
WORKDIR /app
119

12-
# Copy source code
13-
COPY . .
10+
# Force install without any prompts
11+
RUN --mount=type=cache,target=/root/.pnpm-store HUSKY=0 pnpm install --force --no-optional --frozen-lockfile --ignore-scripts --prod
1412

15-
# Build the application
16-
RUN pnpm build
13+
FROM node:22-alpine AS release
1714

18-
# Production stage
19-
FROM node:20-alpine
15+
# Install pnpm
16+
RUN npm install -g pnpm
2017

2118
WORKDIR /app
2219

23-
# Copy only the necessary files from the builder stage
24-
COPY --from=builder /app/dist ./dist
25-
COPY --from=builder /app/package.json ./
26-
COPY --from=builder /app/pnpm-lock.yaml ./
27-
28-
# Install only production dependencies
29-
RUN npm install -g pnpm && \
30-
HUSKY=0 pnpm install --prod --ignore-scripts
31-
32-
# Expose the port for SSE mode
33-
EXPOSE 3000
20+
COPY --from=builder /app/dist /app/dist
21+
COPY --from=builder /app/package.json /app/package.json
22+
COPY --from=builder /app/pnpm-lock.yaml /app/pnpm-lock.yaml
3423

3524
# Set default environment variables
3625
ENV NODE_ENV=production
37-
ENV MCP_TRANSPORT_MODE=sse
38-
ENV MCP_SERVER_PORT=3000
26+
ENV MCP_TRANSPORT_MODE=rest
27+
ENV MCP_SERVER_PORT=3001
28+
29+
# Remove node_modules if exists to avoid prompts
30+
RUN rm -rf node_modules || true
31+
RUN pnpm install --force --no-optional --frozen-lockfile --ignore-scripts --prod
3932

40-
# Run the server in SSE mode
41-
CMD ["node", "dist/index.js"]
33+
ENTRYPOINT ["node", "dist/index.js"]

README.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ Get started with the Storacha MCP Storage Server in just a few simple steps.
9393
"command": "node",
9494
"args": ["./dist/index.js"],
9595
"env": {
96-
// The server also supports `sse` mode, the default is `stdio`.
96+
// The server supports `stdio`, `sse`, and `rest` modes, the default is `stdio`.
9797
"MCP_TRANSPORT_MODE": "stdio",
9898
// The Storacha Agent private key that is authorized to store data into the Space.
9999
"PRIVATE_KEY": "<agent_private_key>",
@@ -109,6 +109,22 @@ Get started with the Storacha MCP Storage Server in just a few simple steps.
109109

110110
_Replace `<agent_private_key>` with the PrivateKey you created in step 3. Then, replace the `<base64_delegation>` with the delegation you created in step 3._
111111

112+
### REST Mode and Cloud Hosting
113+
114+
The Storacha MCP Storage Server supports REST transport mode, which is compatible with MCP.so cloud hosting. To use REST mode:
115+
116+
```jsonc
117+
{
118+
"mcpServers": {
119+
"storacha-storage-server-rest": {
120+
"url": "http://localhost:3001/rest",
121+
},
122+
},
123+
}
124+
```
125+
126+
For more information on deploying to MCP.so cloud, see the [integrations.md](https://github.com/storacha/mcp-storage-server/blob/main/docs/integrations.md#mcpso-cloud-hosting) guide.
127+
112128
_:warning: There are several ways to configure MCP clients, please read the [integrations.md](https://github.com/storacha/mcp-storage-server/blob/main/docs/integrations.md) guide for more information._
113129

114130
## Tools

chatmcp.yaml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
params:
2+
type: object
3+
properties:
4+
PRIVATE_KEY:
5+
type: string
6+
description: The Storacha Agent private key
7+
DELEGATION:
8+
type: string
9+
description: Base64 encoded delegation
10+
required:
11+
- PRIVATE_KEY
12+
- DELEGATION
13+
14+
rest:
15+
name: storacha-storage
16+
port: 3001
17+
endpoint: /rest
18+
dockerfile: ./Dockerfile
19+
20+
docker:
21+
command: |
22+
docker run -i --rm -p 3001:3001 -e PRIVATE_KEY={PRIVATE_KEY} -e DELEGATION={DELEGATION} -e MCP_TRANSPORT_MODE=rest -e MCP_SERVER_PORT=3001 storacha-mcp-server
23+
config: |
24+
{
25+
"mcpServers": {
26+
"storacha-storage": {
27+
"command": "docker",
28+
"args": [
29+
"run",
30+
"-i",
31+
"--rm",
32+
"-p",
33+
"3001:3001",
34+
"-e",
35+
"PRIVATE_KEY",
36+
"-e",
37+
"DELEGATION",
38+
"-e",
39+
"MCP_TRANSPORT_MODE=rest",
40+
"-e",
41+
"MCP_SERVER_PORT=3001",
42+
"storacha-mcp-server"
43+
],
44+
"env": {
45+
"PRIVATE_KEY": "YOUR_PRIVATE_KEY_HERE",
46+
"DELEGATION": "YOUR_DELEGATION_HERE"
47+
}
48+
}
49+
}
50+
}

docs/integrations.md

Lines changed: 94 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,26 @@
22

33
## Start Your Server
44

5-
You can run the MCP server in two different modes:
5+
You can run the MCP server in multiple different modes:
66

77
- **Local Communication**
88

99
```bash
1010
pnpm start:stdio
1111
```
1212

13-
- **Remote Communication**
13+
- **Remote Communication (SSE)**
1414

1515
```bash
1616
pnpm start:sse
1717
```
1818

19+
- **Remote Communication (REST)**
20+
21+
```bash
22+
pnpm start:rest
23+
```
24+
1925
## Client Integrations
2026

2127
You can integrate your client with Storacha MCP Storage Server with any of the following patterns.
@@ -82,6 +88,42 @@ client = new Client(
8288
await client.connect(transport);
8389
```
8490

91+
### SDK (rest mode)
92+
93+
Uses Express with REST for HTTP-based communication. This mode is compatible with MCP.so cloud hosting.
94+
95+
```typescript
96+
import { fetch } from 'node-fetch';
97+
98+
// Make direct JSON-RPC requests to the REST endpoint
99+
async function callTool(toolName, args) {
100+
const response = await fetch(`http://${HOST}:${PORT}/rest`, {
101+
method: 'POST',
102+
headers: {
103+
'Content-Type': 'application/json',
104+
},
105+
body: JSON.stringify({
106+
jsonrpc: '2.0',
107+
id: 'client-request',
108+
method: 'tools/call',
109+
params: {
110+
name: toolName,
111+
arguments: args,
112+
},
113+
}),
114+
});
115+
116+
return await response.json();
117+
}
118+
119+
// Example: Upload a file
120+
const fileContent = Buffer.from('test content').toString('base64');
121+
const result = await callTool('upload', {
122+
file: fileContent,
123+
name: 'test-file.txt',
124+
});
125+
```
126+
85127
### MCP Client Config
86128

87129
Most MCP clients store the configuration as JSON in the following format:
@@ -93,7 +135,7 @@ Most MCP clients store the configuration as JSON in the following format:
93135
"command": "node",
94136
"args": ["./dist/index.js"],
95137
"env": {
96-
// The server also supports `sse` mode, the default is `stdio`.
138+
// The server supports `stdio`, `sse`, and `rest` modes, the default is `stdio`.
97139
"MCP_TRANSPORT_MODE": "stdio",
98140
// The Storacha Agent private key that is authorized to store data into the Space.
99141
"PRIVATE_KEY": "<agent_private_key>",
@@ -111,7 +153,7 @@ Replace `<agent_private_key>` and `<base64_delegation>` with your actual values.
111153

112154
### Docker
113155

114-
You can run the Storacha MCP Storage Server in a Docker container, which makes it easy to deploy across different environments without worrying about dependencies or configuration. It uses SSE mode by default.
156+
You can run the Storacha MCP Storage Server in a Docker container, which makes it easy to deploy across different environments without worrying about dependencies or configuration. It uses SSE mode by default but can be configured to use REST mode.
115157

116158
### Building the Docker Image
117159

@@ -125,19 +167,50 @@ docker build -t storacha-mcp-server .
125167
docker run -p 3000:3000 \
126168
-e PRIVATE_KEY="<agent_private_key>" \
127169
-e DELEGATION="<base64_delegation>" \
170+
-e MCP_TRANSPORT_MODE="sse" \
171+
-e MCP_SERVER_PORT="3001" \
172+
storacha-mcp-server
173+
```
174+
175+
### Running the Server in REST Mode
176+
177+
```bash
178+
docker run -p 3001:3001 \
179+
-e PRIVATE_KEY="<agent_private_key>" \
180+
-e DELEGATION="<base64_delegation>" \
181+
-e MCP_TRANSPORT_MODE="rest" \
182+
-e MCP_SERVER_PORT="3001" \
128183
storacha-mcp-server
129184
```
130185

131186
Replace `<agent_private_key>` and `<base64_delegation>` with your actual values.
132187

188+
In case you want to keep the private key and delegation in a `.env` file, you can run the following:
189+
190+
```bash
191+
source .env && docker run -p 3001:3001 \
192+
-e PRIVATE_KEY="$PRIVATE_KEY" \
193+
-e DELEGATION="$DELEGATION" \
194+
-e MCP_TRANSPORT_MODE=rest \
195+
-e MCP_SERVER_PORT=3001 \
196+
storacha-mcp-server
197+
```
198+
199+
Test the REST connection:
200+
201+
```bash
202+
curl -X POST http://127.0.0.1:3001/rest -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":"2","method":"tools/list"}' | jq
203+
```
204+
133205
### Environment Variables
134206

135-
| Variable | Description | Default |
136-
| -------------------- | --------------------------------- | -------- |
137-
| `MCP_TRANSPORT_MODE` | Transport mode (`stdio` or `sse`) | `sse` |
138-
| `MCP_SERVER_PORT` | Port for SSE mode | `3000` |
139-
| `PRIVATE_KEY` | The Storacha Agent private key | required |
140-
| `DELEGATION` | Base64 encoded delegation | optional |
207+
| Variable | Description | Default |
208+
| -------------------- | ------------------------------------------ | --------- |
209+
| `MCP_TRANSPORT_MODE` | Transport mode (`stdio`, `sse`, or `rest`) | `stdio` |
210+
| `MCP_SERVER_PORT` | Port for SSE or REST mode | `3001` |
211+
| `MCP_SERVER_HOST` | Host for SSE or REST mode | `0.0.0.0` |
212+
| `PRIVATE_KEY` | The Storacha Agent private key | required |
213+
| `DELEGATION` | Base64 encoded delegation | optional |
141214

142215
### Docker Compose Example
143216

@@ -148,12 +221,12 @@ services:
148221
build:
149222
context: .
150223
ports:
151-
- '3000:3000'
224+
- '3001:3001'
152225
environment:
153226
- PRIVATE_KEY=<agent_private_key>
154227
- DELEGATION=<base64_delegation>
155-
- MCP_TRANSPORT_MODE=sse
156-
- MCP_SERVER_PORT=3000
228+
- MCP_TRANSPORT_MODE=rest
229+
- MCP_SERVER_PORT=3001
157230
```
158231
159232
### MCP Client Configuration for Docker SSE Mode
@@ -172,6 +245,14 @@ For Cursor IDE or other MCP clients, you can use this configuration:
172245
}
173246
```
174247

248+
### MCP.so Cloud Hosting
249+
250+
The Storacha MCP Storage Server can be deployed to MCP.so cloud using the REST transport mode. This allows your server to be accessible from anywhere without having to manage your own infrastructure.
251+
252+
Find the Storacha MCP Storage Server on the [MCP Playground](https://mcp.so/playground?server=storacha-storage), set the Private Key and the Delegation, and you are ready to go.
253+
254+
For more details on hosting your MCP server on MCP.so, see the [official documentation](https://docs.mcp.so/server-hosting).
255+
175256
### Tools
176257

177258
#### List Tools

index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { loadConfig as loadStorageConfig } from './src/core/storage/config.js';
99
* Server mode is determined by the MCP_TRANSPORT_MODE environment variable:
1010
* - 'stdio': Starts the server in stdio mode (default)
1111
* - 'http': Starts the server in HTTP mode with SSE transport
12+
* - 'rest': Starts the server in REST mode (MCP.so Cloud)
1213
*/
1314
async function main() {
1415
try {

package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"start": "node dist/index.js",
1414
"start:stdio": "MCP_TRANSPORT_MODE=stdio pnpm start",
1515
"start:sse": "MCP_TRANSPORT_MODE=sse pnpm start",
16+
"start:rest": "MCP_TRANSPORT_MODE=rest pnpm start",
1617
"dev": "tsc-watch --onSuccess \"node dist/index.js\"",
1718
"clean": "rm -rf dist",
1819
"lint": "eslint \"src/**/*.{ts,tsx}\" \"test/**/*.{ts,tsx}\"",
@@ -23,9 +24,11 @@
2324
"test:coverage": "pnpm typecheck && vitest run --coverage",
2425
"test": "pnpm typecheck && vitest run",
2526
"test:integration": "pnpm build && pnpm typecheck && vitest run test/integration/**.test.ts",
27+
"test:integration:only": "pnpm build && pnpm typecheck && vitest run",
2628
"inspect": "pnpm build && npx @modelcontextprotocol/inspector node dist/index.js",
2729
"inspect:sse": "MCP_TRANSPORT_MODE=sse pnpm inspect",
2830
"inspect:stdio": "MCP_TRANSPORT_MODE=stdio pnpm inspect",
31+
"inspect:rest": "MCP_TRANSPORT_MODE=rest pnpm inspect",
2932
"prepare": "husky install",
3033
"prepublishOnly": "pnpm build"
3134
},
@@ -51,6 +54,7 @@
5154
"dist"
5255
],
5356
"dependencies": {
57+
"@chatmcp/sdk": "^1.0.6",
5458
"@ipld/car": "^5.4.0",
5559
"@ipld/dag-json": "^10.2.3",
5660
"@ipld/unixfs": "^3.0.0",
@@ -72,13 +76,15 @@
7276
"@types/cors": "^2.8.17",
7377
"@types/express": "^5.0.1",
7478
"@types/node": "^22.13.13",
79+
"@types/node-fetch": "^2.6.12",
7580
"@typescript-eslint/eslint-plugin": "^8.29.0",
7681
"@typescript-eslint/parser": "^8.29.0",
7782
"@vitest/coverage-v8": "3.0.9",
7883
"eslint": "^9.23.0",
7984
"eslint-config-prettier": "^10.1.1",
8085
"husky": "^9.1.7",
8186
"lint-staged": "^15.5.0",
87+
"node-fetch": "^3.3.2",
8288
"prettier": "^3.5.3",
8389
"ts-node": "^10.9.2",
8490
"tsc-watch": "^6.2.1",

0 commit comments

Comments
 (0)