├── .editorconfig
├── .gitignore
├── Dockerfile
├── LICENSE
├── README.md
├── biome.json
├── package-lock.json
├── package.json
├── smithery.yaml
├── src
├── docs
│ └── about-databutton.ts
├── enums.ts
├── index.ts
├── tools
│ └── submit-app-requirements.ts
├── types.ts
└── utils
│ ├── response-utils.ts
│ └── tool-request-utils.ts
└── tsconfig.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | end_of_line = lf
5 | insert_final_newline = true
6 | trim_trailing_whitespace = true
7 | charset = utf-8
8 | indent_style = space
9 | indent_size = 2
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | build/
3 | *.log
4 | .env*
5 | notes/
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | # Generated by https://smithery.ai. See: https://smithery.ai/docs/config#dockerfile
2 | FROM node:lts-alpine
3 |
4 | # Create app directory
5 | WORKDIR /app
6 |
7 | # Copy package files
8 | COPY package*.json ./
9 |
10 | # Install dependencies but ignore prepare scripts
11 | RUN npm install --ignore-scripts
12 |
13 | # Copy source code
14 | COPY . .
15 |
16 | # Build the project
17 | RUN npm run build
18 |
19 | # Expose the port if needed (but MCP uses stdio, so not needed)
20 |
21 | # Run the MCP server
22 | CMD ["node", "build/index.js"]
23 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2025 databutton
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Databutton MCP – build your own MCPs
2 |
3 | We released a game changing way for anyone to build their own MCP servers in Databutton.
4 | Learn more at https://www.databutton.com/mcp
5 |
6 | # Databutton MCP Server
7 |
8 | Databutton's () AI agent builds and deploys frontends and backends in React and Python APIs/MCPs, for building beautiful business apps with unbounded complexity.
9 |
10 | The agent has a planning mode for generating an initial plan for your app.
11 |
12 | This MCP server is for doing doing initial app planning and creating a good starting point for an app.
13 |
14 | ## Installation
15 |
16 | To use with Claude Desktop, add the server config:
17 |
18 | On MacOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
19 | On Windows: `%APPDATA%/Claude/claude_desktop_config.json`
20 |
21 | ```json
22 | {
23 | "mcpServers": {
24 | "databutton": {
25 | "command": "/path/to/databutton/build/index.js"
26 | }
27 | }
28 | }
29 | ```
30 |
31 | ## Development
32 |
33 | Install dependencies:
34 |
35 | ```bash
36 | npm install
37 | ```
38 |
39 | Build the server:
40 |
41 | ```bash
42 | npm run build
43 | ```
44 |
45 | For development with auto-rebuild:
46 |
47 | ```bash
48 | npm run watch
49 | ```
50 |
51 | ### Debugging
52 |
53 | Since MCP servers communicate over stdio, debugging can be challenging. We recommend using the [MCP Inspector](https://github.com/modelcontextprotocol/inspector), which is available as a package script:
54 |
55 | ```bash
56 | npm run inspector
57 | ```
58 |
59 | The Inspector will provide a URL to access debugging tools in your browser.
60 |
--------------------------------------------------------------------------------
/biome.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
3 | "vcs": {
4 | "enabled": false,
5 | "clientKind": "git",
6 | "useIgnoreFile": false
7 | },
8 | "files": {
9 | "ignoreUnknown": false,
10 | "ignore": []
11 | },
12 | "formatter": {
13 | "enabled": true,
14 | "indentStyle": "tab"
15 | },
16 | "organizeImports": {
17 | "enabled": true
18 | },
19 | "linter": {
20 | "enabled": true,
21 | "rules": {
22 | "recommended": true
23 | }
24 | },
25 | "javascript": {
26 | "formatter": {
27 | "quoteStyle": "double"
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "databutton",
3 | "version": "0.1.0",
4 | "lockfileVersion": 3,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "databutton",
9 | "version": "0.1.0",
10 | "dependencies": {
11 | "@modelcontextprotocol/sdk": "0.6.0",
12 | "zod": "3.24.1",
13 | "zod-to-json-schema": "3.24.1",
14 | "zod-validation-error": "3.4.0"
15 | },
16 | "bin": {
17 | "databutton": "build/index.js"
18 | },
19 | "devDependencies": {
20 | "@biomejs/biome": "1.9.4",
21 | "@types/diff": "7.0.0",
22 | "@types/node": "^20.11.24",
23 | "typescript": "^5.3.3"
24 | }
25 | },
26 | "node_modules/@biomejs/biome": {
27 | "version": "1.9.4",
28 | "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.9.4.tgz",
29 | "integrity": "sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog==",
30 | "dev": true,
31 | "hasInstallScript": true,
32 | "license": "MIT OR Apache-2.0",
33 | "bin": {
34 | "biome": "bin/biome"
35 | },
36 | "engines": {
37 | "node": ">=14.21.3"
38 | },
39 | "funding": {
40 | "type": "opencollective",
41 | "url": "https://opencollective.com/biome"
42 | },
43 | "optionalDependencies": {
44 | "@biomejs/cli-darwin-arm64": "1.9.4",
45 | "@biomejs/cli-darwin-x64": "1.9.4",
46 | "@biomejs/cli-linux-arm64": "1.9.4",
47 | "@biomejs/cli-linux-arm64-musl": "1.9.4",
48 | "@biomejs/cli-linux-x64": "1.9.4",
49 | "@biomejs/cli-linux-x64-musl": "1.9.4",
50 | "@biomejs/cli-win32-arm64": "1.9.4",
51 | "@biomejs/cli-win32-x64": "1.9.4"
52 | }
53 | },
54 | "node_modules/@biomejs/cli-darwin-arm64": {
55 | "version": "1.9.4",
56 | "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.9.4.tgz",
57 | "integrity": "sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw==",
58 | "cpu": [
59 | "arm64"
60 | ],
61 | "dev": true,
62 | "license": "MIT OR Apache-2.0",
63 | "optional": true,
64 | "os": [
65 | "darwin"
66 | ],
67 | "engines": {
68 | "node": ">=14.21.3"
69 | }
70 | },
71 | "node_modules/@biomejs/cli-darwin-x64": {
72 | "version": "1.9.4",
73 | "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.9.4.tgz",
74 | "integrity": "sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg==",
75 | "cpu": [
76 | "x64"
77 | ],
78 | "dev": true,
79 | "license": "MIT OR Apache-2.0",
80 | "optional": true,
81 | "os": [
82 | "darwin"
83 | ],
84 | "engines": {
85 | "node": ">=14.21.3"
86 | }
87 | },
88 | "node_modules/@biomejs/cli-linux-arm64": {
89 | "version": "1.9.4",
90 | "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.9.4.tgz",
91 | "integrity": "sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g==",
92 | "cpu": [
93 | "arm64"
94 | ],
95 | "dev": true,
96 | "license": "MIT OR Apache-2.0",
97 | "optional": true,
98 | "os": [
99 | "linux"
100 | ],
101 | "engines": {
102 | "node": ">=14.21.3"
103 | }
104 | },
105 | "node_modules/@biomejs/cli-linux-arm64-musl": {
106 | "version": "1.9.4",
107 | "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.9.4.tgz",
108 | "integrity": "sha512-v665Ct9WCRjGa8+kTr0CzApU0+XXtRgwmzIf1SeKSGAv+2scAlW6JR5PMFo6FzqqZ64Po79cKODKf3/AAmECqA==",
109 | "cpu": [
110 | "arm64"
111 | ],
112 | "dev": true,
113 | "license": "MIT OR Apache-2.0",
114 | "optional": true,
115 | "os": [
116 | "linux"
117 | ],
118 | "engines": {
119 | "node": ">=14.21.3"
120 | }
121 | },
122 | "node_modules/@biomejs/cli-linux-x64": {
123 | "version": "1.9.4",
124 | "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-1.9.4.tgz",
125 | "integrity": "sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg==",
126 | "cpu": [
127 | "x64"
128 | ],
129 | "dev": true,
130 | "license": "MIT OR Apache-2.0",
131 | "optional": true,
132 | "os": [
133 | "linux"
134 | ],
135 | "engines": {
136 | "node": ">=14.21.3"
137 | }
138 | },
139 | "node_modules/@biomejs/cli-linux-x64-musl": {
140 | "version": "1.9.4",
141 | "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-1.9.4.tgz",
142 | "integrity": "sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg==",
143 | "cpu": [
144 | "x64"
145 | ],
146 | "dev": true,
147 | "license": "MIT OR Apache-2.0",
148 | "optional": true,
149 | "os": [
150 | "linux"
151 | ],
152 | "engines": {
153 | "node": ">=14.21.3"
154 | }
155 | },
156 | "node_modules/@biomejs/cli-win32-arm64": {
157 | "version": "1.9.4",
158 | "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.9.4.tgz",
159 | "integrity": "sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg==",
160 | "cpu": [
161 | "arm64"
162 | ],
163 | "dev": true,
164 | "license": "MIT OR Apache-2.0",
165 | "optional": true,
166 | "os": [
167 | "win32"
168 | ],
169 | "engines": {
170 | "node": ">=14.21.3"
171 | }
172 | },
173 | "node_modules/@biomejs/cli-win32-x64": {
174 | "version": "1.9.4",
175 | "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-1.9.4.tgz",
176 | "integrity": "sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA==",
177 | "cpu": [
178 | "x64"
179 | ],
180 | "dev": true,
181 | "license": "MIT OR Apache-2.0",
182 | "optional": true,
183 | "os": [
184 | "win32"
185 | ],
186 | "engines": {
187 | "node": ">=14.21.3"
188 | }
189 | },
190 | "node_modules/@modelcontextprotocol/sdk": {
191 | "version": "0.6.0",
192 | "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-0.6.0.tgz",
193 | "integrity": "sha512-9rsDudGhDtMbvxohPoMMyAUOmEzQsOK+XFchh6gZGqo8sx9sBuZQs+CUttXqa8RZXKDaJRCN2tUtgGof7jRkkw==",
194 | "license": "MIT",
195 | "dependencies": {
196 | "content-type": "^1.0.5",
197 | "raw-body": "^3.0.0",
198 | "zod": "^3.23.8"
199 | }
200 | },
201 | "node_modules/@types/diff": {
202 | "version": "7.0.0",
203 | "resolved": "https://registry.npmjs.org/@types/diff/-/diff-7.0.0.tgz",
204 | "integrity": "sha512-sVpkpbnTJL9CYoDf4U+tHaQLe5HiTaHWY7m9FuYA7oMCHwC9ie0Vh9eIGapyzYrU3+pILlSY2fAc4elfw5m4dg==",
205 | "dev": true,
206 | "license": "MIT"
207 | },
208 | "node_modules/@types/node": {
209 | "version": "20.17.24",
210 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.24.tgz",
211 | "integrity": "sha512-d7fGCyB96w9BnWQrOsJtpyiSaBcAYYr75bnK6ZRjDbql2cGLj/3GsL5OYmLPNq76l7Gf2q4Rv9J2o6h5CrD9sA==",
212 | "dev": true,
213 | "license": "MIT",
214 | "dependencies": {
215 | "undici-types": "~6.19.2"
216 | }
217 | },
218 | "node_modules/bytes": {
219 | "version": "3.1.2",
220 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
221 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
222 | "license": "MIT",
223 | "engines": {
224 | "node": ">= 0.8"
225 | }
226 | },
227 | "node_modules/content-type": {
228 | "version": "1.0.5",
229 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
230 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
231 | "license": "MIT",
232 | "engines": {
233 | "node": ">= 0.6"
234 | }
235 | },
236 | "node_modules/depd": {
237 | "version": "2.0.0",
238 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
239 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
240 | "license": "MIT",
241 | "engines": {
242 | "node": ">= 0.8"
243 | }
244 | },
245 | "node_modules/http-errors": {
246 | "version": "2.0.0",
247 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
248 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
249 | "license": "MIT",
250 | "dependencies": {
251 | "depd": "2.0.0",
252 | "inherits": "2.0.4",
253 | "setprototypeof": "1.2.0",
254 | "statuses": "2.0.1",
255 | "toidentifier": "1.0.1"
256 | },
257 | "engines": {
258 | "node": ">= 0.8"
259 | }
260 | },
261 | "node_modules/iconv-lite": {
262 | "version": "0.6.3",
263 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
264 | "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
265 | "license": "MIT",
266 | "dependencies": {
267 | "safer-buffer": ">= 2.1.2 < 3.0.0"
268 | },
269 | "engines": {
270 | "node": ">=0.10.0"
271 | }
272 | },
273 | "node_modules/inherits": {
274 | "version": "2.0.4",
275 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
276 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
277 | "license": "ISC"
278 | },
279 | "node_modules/raw-body": {
280 | "version": "3.0.0",
281 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz",
282 | "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==",
283 | "license": "MIT",
284 | "dependencies": {
285 | "bytes": "3.1.2",
286 | "http-errors": "2.0.0",
287 | "iconv-lite": "0.6.3",
288 | "unpipe": "1.0.0"
289 | },
290 | "engines": {
291 | "node": ">= 0.8"
292 | }
293 | },
294 | "node_modules/safer-buffer": {
295 | "version": "2.1.2",
296 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
297 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
298 | "license": "MIT"
299 | },
300 | "node_modules/setprototypeof": {
301 | "version": "1.2.0",
302 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
303 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
304 | "license": "ISC"
305 | },
306 | "node_modules/statuses": {
307 | "version": "2.0.1",
308 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
309 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
310 | "license": "MIT",
311 | "engines": {
312 | "node": ">= 0.8"
313 | }
314 | },
315 | "node_modules/toidentifier": {
316 | "version": "1.0.1",
317 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
318 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
319 | "license": "MIT",
320 | "engines": {
321 | "node": ">=0.6"
322 | }
323 | },
324 | "node_modules/typescript": {
325 | "version": "5.8.2",
326 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz",
327 | "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==",
328 | "dev": true,
329 | "license": "Apache-2.0",
330 | "bin": {
331 | "tsc": "bin/tsc",
332 | "tsserver": "bin/tsserver"
333 | },
334 | "engines": {
335 | "node": ">=14.17"
336 | }
337 | },
338 | "node_modules/undici-types": {
339 | "version": "6.19.8",
340 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
341 | "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
342 | "dev": true,
343 | "license": "MIT"
344 | },
345 | "node_modules/unpipe": {
346 | "version": "1.0.0",
347 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
348 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
349 | "license": "MIT",
350 | "engines": {
351 | "node": ">= 0.8"
352 | }
353 | },
354 | "node_modules/zod": {
355 | "version": "3.24.1",
356 | "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.1.tgz",
357 | "integrity": "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==",
358 | "license": "MIT",
359 | "funding": {
360 | "url": "https://github.com/sponsors/colinhacks"
361 | }
362 | },
363 | "node_modules/zod-to-json-schema": {
364 | "version": "3.24.1",
365 | "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.1.tgz",
366 | "integrity": "sha512-3h08nf3Vw3Wl3PK+q3ow/lIil81IT2Oa7YpQyUUDsEWbXveMesdfK1xBd2RhCkynwZndAxixji/7SYJJowr62w==",
367 | "license": "ISC",
368 | "peerDependencies": {
369 | "zod": "^3.24.1"
370 | }
371 | },
372 | "node_modules/zod-validation-error": {
373 | "version": "3.4.0",
374 | "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-3.4.0.tgz",
375 | "integrity": "sha512-ZOPR9SVY6Pb2qqO5XHt+MkkTRxGXb4EVtnjc9JpXUOtUB1T9Ru7mZOT361AN3MsetVe7R0a1KZshJDZdgp9miQ==",
376 | "license": "MIT",
377 | "engines": {
378 | "node": ">=18.0.0"
379 | },
380 | "peerDependencies": {
381 | "zod": "^3.18.0"
382 | }
383 | }
384 | }
385 | }
386 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "databutton",
3 | "version": "0.1.0",
4 | "description": "A MCP server for Databutton",
5 | "private": true,
6 | "type": "module",
7 | "bin": {
8 | "databutton": "./build/index.js"
9 | },
10 | "files": [
11 | "build"
12 | ],
13 | "scripts": {
14 | "build": "tsc && node -e \"require('fs').chmodSync('build/index.js', '755')\"",
15 | "prepare": "npm run build",
16 | "watch": "tsc --watch",
17 | "inspector": "npx @modelcontextprotocol/inspector build/index.js"
18 | },
19 | "dependencies": {
20 | "@modelcontextprotocol/sdk": "0.6.0",
21 | "zod": "3.24.1",
22 | "zod-to-json-schema": "3.24.1",
23 | "zod-validation-error": "3.4.0"
24 | },
25 | "devDependencies": {
26 | "@biomejs/biome": "1.9.4",
27 | "@types/diff": "7.0.0",
28 | "@types/node": "^20.11.24",
29 | "typescript": "^5.3.3"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/smithery.yaml:
--------------------------------------------------------------------------------
1 | # Smithery configuration file: https://smithery.ai/docs/config#smitheryyaml
2 |
3 | startCommand:
4 | type: stdio
5 | configSchema:
6 | # JSON Schema defining the configuration options for the MCP.
7 | type: object
8 | properties: {}
9 | commandFunction:
10 | # A JS function that produces the CLI command based on the given config to start the MCP on stdio.
11 | |-
12 | (config) => ({ command: 'node', args: ['build/index.js'] })
13 | exampleConfig: {}
14 |
--------------------------------------------------------------------------------
/src/docs/about-databutton.ts:
--------------------------------------------------------------------------------
1 | export const ABOUT_DATABUTTON = `
2 | # About Databutton
3 |
4 | Databutton is an online workspace for rapid prototyping, building, and deploying apps. These apps often utilize AI to provide value.
5 |
6 | ## Structure of a Typical AI App
7 |
8 | This is the structure of a typical AI app built in Databutton:
9 |
10 | 1. A FastAPI API which is exposed to the frontend via the generated TypeScript HTTP client named "brain". It is organized as a set of APIs, each of which adds endpoints to a router. An API will often have only one endpoint but can be used to group closely related endpoints.
11 |
12 | 2. A web app built using React and Typescript. This is the UI the user builds on top of APIs and storage. The web app consists of pages and UI components. If the user is using firebase, firestore or supabase, reads and writes are handled directly from the frontend code.
13 |
14 | 3. Reusable UI components and UI files that the user can use in throughout the app. These should be used to keep the UI consistent and to make it easier to build new pages. It will also contribute to smaller files which are easier to maintain.
15 |
16 | 4. Store frontend-specific config such as firebase config and supabase urls in UI files.
17 |
18 | 5. Secrets such as API keys, database connection strings, and other sensitive information. The secrets are only available from the API, not the UI. We call this storage "db.secrets".
19 |
20 | 6. Internal storage where we store DataFrames, binary files, text files, and JSON. The internal storage is only available from the API, not the UI. We call this storage "db.storage".
21 |
22 | 7. Media (static assets) such as images, videos, and other files. These files are publicly accessible to anyone with the URL. These are public and can be accessed by anyone.
23 |
24 | 8. Extensions which are a way to add additional functionality to the app.
25 | `.trim();
26 |
--------------------------------------------------------------------------------
/src/enums.ts:
--------------------------------------------------------------------------------
1 | export enum ToolName {
2 | SUBMIT_APP_REQUIREMENTS = "submit_app_requirements",
3 | }
4 |
5 | export enum PromptName {
6 | DISCUSS_APP_IDEA = "discuss_app_idea",
7 | }
8 |
9 | export enum ResourceName {
10 | ABOUT_DATABUTTON = "about_databutton.md",
11 | }
12 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | import { Server } from "@modelcontextprotocol/sdk/server/index.js";
4 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5 | import {
6 | CallToolRequestSchema,
7 | GetPromptRequestSchema,
8 | ListPromptsRequestSchema,
9 | ListResourcesRequestSchema,
10 | ListToolsRequestSchema,
11 | ReadResourceRequestSchema,
12 | } from "@modelcontextprotocol/sdk/types.js";
13 | import { ABOUT_DATABUTTON } from "./docs/about-databutton.js";
14 | import { PromptName, ResourceName } from "./enums.js";
15 | import {
16 | submitAppRequirementsDef,
17 | submitAppRequirementsImpl,
18 | } from "./tools/submit-app-requirements.js";
19 |
20 | /**
21 | * Create an MCP server
22 | */
23 | const server = new Server(
24 | {
25 | name: "Databutton MCP Server",
26 | version: "0.1.0",
27 | },
28 | {
29 | capabilities: {
30 | resources: {},
31 | tools: {},
32 | prompts: {},
33 | },
34 | },
35 | );
36 |
37 | server.setRequestHandler(ListResourcesRequestSchema, async () => {
38 | return {
39 | resources: [
40 | {
41 | uri: `doc://${ResourceName.ABOUT_DATABUTTON}`,
42 | name: "About Databutton",
43 | description: "Learn more about Databutton",
44 | mimeType: "text/markdown",
45 | },
46 | ],
47 | };
48 | });
49 |
50 | server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
51 | console.error(`Reading task ${request.params.uri}`);
52 |
53 | const id = request.params.uri.replace(/^doc:\/\//, "");
54 |
55 | if (id === ResourceName.ABOUT_DATABUTTON) {
56 | return {
57 | contents: [
58 | {
59 | uri: request.params.uri,
60 | mimeType: "text/markdown",
61 | text: ABOUT_DATABUTTON,
62 | },
63 | ],
64 | };
65 | }
66 |
67 | throw new Error("Resource not found");
68 | });
69 |
70 | /**
71 | * Handler that lists available tools.
72 | */
73 | server.setRequestHandler(ListToolsRequestSchema, async () => {
74 | return {
75 | tools: [submitAppRequirementsDef],
76 | };
77 | });
78 |
79 | /**
80 | * Handler for tool calls
81 | */
82 | server.setRequestHandler(CallToolRequestSchema, async (request) => {
83 | switch (request.params.name) {
84 | case submitAppRequirementsDef.name: {
85 | return await submitAppRequirementsImpl(request.params.arguments);
86 | }
87 |
88 | default:
89 | throw new Error("Unknown tool");
90 | }
91 | });
92 |
93 | /**
94 | * Handler that lists available prompts.
95 | * Exposes a single "summarize_notes" prompt that summarizes all notes.
96 | */
97 | server.setRequestHandler(ListPromptsRequestSchema, async () => {
98 | return {
99 | prompts: [
100 | {
101 | name: PromptName.DISCUSS_APP_IDEA,
102 | description: "Discuss an app idea",
103 | },
104 | ],
105 | };
106 | });
107 |
108 | /**
109 | * Handler for the summarize_notes prompt.
110 | * Returns a prompt that requests summarization of all notes, with the notes' contents embedded as resources.
111 | */
112 | server.setRequestHandler(GetPromptRequestSchema, async (request) => {
113 | if (request.params.name === PromptName.DISCUSS_APP_IDEA) {
114 | return {
115 | messages: [
116 | {
117 | role: "user",
118 | content: {
119 | type: "text",
120 | text: "I have an app idea I want to discuss. Let's talk about it in the context of Databutton. To learn more read the Databutton resources. When we agree on a simply MVP scope we should submit the app requirements.",
121 | },
122 | },
123 | ],
124 | };
125 | }
126 |
127 | throw new Error("Unknown prompt");
128 | });
129 |
130 | /**
131 | * Start the server using stdio transport.
132 | * This allows the server to communicate via standard input/output streams.
133 | */
134 | async function main() {
135 | const transport = new StdioServerTransport();
136 | await server.connect(transport);
137 | }
138 |
139 | main().catch((error) => {
140 | console.error("Server error:", error);
141 | process.exit(1);
142 | });
143 |
--------------------------------------------------------------------------------
/src/tools/submit-app-requirements.ts:
--------------------------------------------------------------------------------
1 | import type { Result } from "@modelcontextprotocol/sdk/types.js";
2 | import { z } from "zod";
3 | import { zodToJsonSchema } from "zod-to-json-schema";
4 | import { ToolName } from "../enums.js";
5 | import type { RawArgs } from "../types.js";
6 | import { buildSimpleResponse } from "../utils/response-utils.js";
7 | import { parseToolInput } from "../utils/tool-request-utils.js";
8 |
9 | const schema = z.object({
10 | name: z.string({
11 | description: "The name of the app",
12 | }),
13 | pitch: z.string({
14 | description: "The pitch for the app",
15 | }),
16 | spec: z.object({
17 | description: z.string({
18 | description:
19 | "The app's specifications given in no more than 4-5 paragraphs",
20 | }),
21 | targetAudience: z.string({
22 | description: "The app's target audience",
23 | }),
24 | design: z.string({
25 | description: "The app's design",
26 | }),
27 | typography: z.string({
28 | description: "The app's typography",
29 | }),
30 | }),
31 | });
32 |
33 | type Input = z.infer;
34 |
35 | export const submitAppRequirementsDef = {
36 | name: ToolName.SUBMIT_APP_REQUIREMENTS,
37 | description: "Submit app requirements",
38 | inputSchema: zodToJsonSchema(schema),
39 | };
40 |
41 | export const submitAppRequirementsImpl = async (
42 | args: RawArgs,
43 | ): Promise => {
44 | const parsed = parseToolInput({ input: args, schema });
45 |
46 | if (parsed.success) {
47 | const base64Encoded = btoa(JSON.stringify(parsed.data));
48 | const urlEncoded = encodeURIComponent(base64Encoded);
49 |
50 | return buildSimpleResponse(
51 | `App requirements submitted. Click the following link to get started: https://databutton.com/submit?requirements=${urlEncoded}`,
52 | );
53 | }
54 |
55 | return buildSimpleResponse(parsed.message);
56 | };
57 |
--------------------------------------------------------------------------------
/src/types.ts:
--------------------------------------------------------------------------------
1 | export type RawArgs = Record | undefined;
2 |
--------------------------------------------------------------------------------
/src/utils/response-utils.ts:
--------------------------------------------------------------------------------
1 | import type { Result } from "@modelcontextprotocol/sdk/types.js";
2 |
3 | export const buildSimpleResponse = (text: string): Result => {
4 | return {
5 | content: [
6 | {
7 | type: "text",
8 | text,
9 | },
10 | ],
11 | };
12 | };
13 |
--------------------------------------------------------------------------------
/src/utils/tool-request-utils.ts:
--------------------------------------------------------------------------------
1 | import type { ZodSchema } from "zod";
2 | import { fromError } from "zod-validation-error";
3 | import type { RawArgs } from "../types.js";
4 |
5 | export const parseToolInput = ({
6 | input,
7 | schema,
8 | }: {
9 | input: RawArgs;
10 | schema: ZodSchema;
11 | }): { success: true; data: T } | { success: false; message: string } => {
12 | const parsed = schema.safeParse(input);
13 |
14 | if (parsed.success) {
15 | return { success: true, data: parsed.data as T };
16 | }
17 |
18 | return { success: false, message: fromError(parsed.error).toString() };
19 | };
20 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2022",
4 | "module": "Node16",
5 | "moduleResolution": "Node16",
6 | "outDir": "./build",
7 | "rootDir": "./src",
8 | "strict": true,
9 | "esModuleInterop": true,
10 | "skipLibCheck": true,
11 | "forceConsistentCasingInFileNames": true
12 | },
13 | "include": ["src/**/*"],
14 | "exclude": ["node_modules"]
15 | }
16 |
--------------------------------------------------------------------------------