Skip to content

Commit 513740e

Browse files
authored
Adding a CONTIRBUTING.md for MCP (#8803)
* Adding a CONTIRBUTING.md for MCP * Add readme regen command * Format'
1 parent 23c3e5f commit 513740e

File tree

1 file changed

+183
-0
lines changed

1 file changed

+183
-0
lines changed

src/mcp/CONTRIBUTING.md

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
# Firebase MCP Server Contributing Guide
2+
3+
## Overview
4+
5+
The Firebase MCP server offers tools that LLMs can use when interacting with Firebase.
6+
The tools let you fetch important context about what is deployed to your project,
7+
access agents that can perform specialized tasks, or make minor modifications to your project.
8+
9+
## Audience
10+
11+
If you are a developer interested in contributing to the MCP server, this is the
12+
documentation for you! This guide describes how to be successful in contributing
13+
to our repository.
14+
15+
## Getting Started
16+
17+
The Firebase MCP server lives alongside the Firebase CLI in the [firebase/firebase-tools][gh-repo] repo.
18+
It lives here so that it can share code for authentication, API calls, and utilities with the CLI.
19+
20+
External developers: If you're interested in contributing code, get started by
21+
[making a fork of the repository for your GitHub account](https://help.github.com/en/github/getting-started-with-github/fork-a-repo).
22+
23+
Internal developers: Go to go/firebase-github-request and ask for access to this repo. You should work
24+
off of sepearate branches in this repo, to ensure that all CI runs correctly for you.
25+
26+
### Contribution Process
27+
28+
External developers: The preferred means of contribution to the MCP server is by creating a branch in your
29+
own fork, pushing your changes there, and submitting a Pull Request to the
30+
`master` branch of `firebase/firebase-tools`.
31+
32+
Internal developers: Instead of working off of a fork, please make a branch on [firebase/firebase-tools][gh-repo]
33+
named <yourInitialsOrLDAP>-<feature> (for example, `jh-dataconnect-tools`)
34+
35+
If your change is visible to users, it should be in the
36+
[changelog](https://github.com/firebase/firebase-tools/releases). Please
37+
add an entry to the `CHANGELOG.md` file. This log is emptied after every release
38+
and is used to generate the release notes posted in the
39+
[Releases](https://github.com/firebase/firebase-tools/releases) page. Markdown
40+
formatting is respected (using the GitHub style).
41+
42+
NOTE: Any new files added to the repository **must** be written in TypeScript
43+
and **must** include unit tests. There are very few exceptions to this rule.
44+
45+
After your Pull Request passes the tests and is approved by a Firebase CLI team
46+
member, they will merge your PR. Thank you for your contribution!
47+
48+
### Setting up your development environment
49+
50+
Please follow the instructions in the [CLI's CONTRIBUTING.md](https://github.com/firebase/firebase-tools/blob/master/CONTRIBUTING.md#setting-up-your-development-environment) to get your development environment set up.
51+
52+
There are a few extra things to set up when developing the MCP server.
53+
54+
### Testing with the MCP Inspector
55+
56+
During early development, you will want to test that your tools outputs what you expect, without burning tokens.
57+
The easiest way to do this is the [MCP inspector](https://github.com/modelcontextprotocol/inspector). From a
58+
Firebase project directory, run:
59+
60+
```
61+
npx -y @modelcontextprotocol/inspector
62+
```
63+
64+
This will print out a localhost link to a simple testing UI. There, you can configure the MCP server
65+
and manually list and execute tools.
66+
67+
```
68+
Transport Type: STDIO
69+
Command: firebase
70+
Arguments: experimental:mcp
71+
72+
```
73+
74+
## Building MCP tools
75+
76+
IMPORTANT: LLMs cannot handle large number of tools. Please consider whether the functionality
77+
you want to add can be added to an existing tool.
78+
79+
### Setting up a new tool
80+
81+
#### Create a file for your tool
82+
83+
First, create a new file in `src/mcp/tools/<product>`.
84+
If your product does not have tools yet, create a new directory under `src/mcp/tools`/.
85+
If the tool is relevant for many Firebase products, put it under `core`.
86+
87+
Tool files should be named `<product>/<foo_tool>`. The tool will then be listed as `<product>_<foo_tool>`.
88+
89+
```typescript
90+
import { z } from "zod";
91+
import { tool } from "../../tool.js";
92+
import { mcpError, toContent } from "../../util.js";
93+
94+
export const foo_bar = tool(
95+
{
96+
name: "foo_bar",
97+
description: "Foos a bar. This description informs LLMs when to use this tool",
98+
inputSchema: z.object({
99+
foo: z
100+
.string()
101+
.describe("The foo to bar. Parameter descriptions inform LLMs how to use this param."),
102+
}),
103+
annotations: {
104+
title: "Foo Bar",
105+
readOnlyHint: true, // True if this tool makes no changes to your local files or Firebase project.
106+
idempotentHint: false, // True if this tool can safely be run multiple times without redundant effects.
107+
destructiveHint: false, // True if this tool deletes files or data.
108+
openWorldHint: false, // Does this tool interact with open (ie the web) or closed systems (ie a Firestore DB)
109+
},
110+
_meta: {
111+
requiresProject: true, // Does this tool require you to be in a Firebase project directory?
112+
requiresAuth: true, // Does this tool require you to be authenticated (usually via `firebase login`)
113+
requiresGemini: true, // Does this tool use Gemini in Firebase in any way?
114+
},
115+
},
116+
async (
117+
{ foo }, // Anything passed in inputSchema is avialable here.
118+
{ projectId, accountEmail, config }, // See ServerToolContext for a complete list of available fields
119+
) => {
120+
// Business logic for the tool
121+
let foo;
122+
try {
123+
const foo = await barFood(prompt, projectId);
124+
} catch (e: any) {
125+
// return mcpError to handle error cases
126+
return mcpError("Foo could not be barred");
127+
}
128+
// Use toContent to return successes in a MCP friendly format.
129+
return toContent(schema);
130+
},
131+
);
132+
```
133+
134+
Here are a few style notes:
135+
136+
- Tool names
137+
- should not include product name
138+
- should be all lower-case letters
139+
- should be snake case
140+
- Descriptions
141+
- should be aimed at informing LLMs, not humans
142+
143+
#### Load the command
144+
145+
Next, go to `src/mcp/tools/<product>/index.ts`, and add your tool:
146+
147+
```typescript
148+
import { foo_bar } from "./foo_bar"
149+
150+
export const <product>Tools = [
151+
foo_bar,
152+
];
153+
154+
```
155+
156+
If this is the first tool for this product, also go to `src/mcp/tools/index.ts` and add your product:
157+
158+
```typescript
159+
import { <product>Tools } from "./<product>/index.js"
160+
161+
const tools: Record<ServerFeature, ServerTool[]> = {
162+
// Exisitng tools here...
163+
<product>: addFeaturePrefix("<product>", <product>Tools),
164+
}
165+
166+
```
167+
168+
### Update the README.md tool list
169+
170+
Run the following command to add your new tool to the list in `src/mcp/README.md`
171+
172+
```
173+
node lib/bin/firebase.js experimental:mcp --generate-tool-list
174+
```
175+
176+
### Logging and terminal formatting
177+
178+
The Firebase CLI has a central logger available in `src/logger`. You should
179+
never use `console.log()` in an MCP tool - STDOUT must only take structured MCP output.
180+
181+
Any logs for your tool will be written to `firebase-debug.log`
182+
183+
[gh-repo]: https://github.com/firebase/firebase-tools

0 commit comments

Comments
 (0)