Skip to content

Commit f148623

Browse files
committed
Merge branch 'main' into ni/feature-flags
2 parents 1162d4c + 0456698 commit f148623

File tree

13 files changed

+385
-75
lines changed

13 files changed

+385
-75
lines changed

.github/workflows/publish.yml

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,6 @@ jobs:
8080
if: needs.check.outputs.VERSION_EXISTS == 'false'
8181
steps:
8282
- uses: GitHubSecurityLab/actions-permissions/monitor@v1
83-
- uses: mongodb-js/devtools-shared/actions/setup-bot-token@main
84-
id: app-token
85-
with:
86-
app-id: ${{ vars.DEVTOOLS_BOT_APP_ID }}
87-
private-key: ${{ secrets.DEVTOOLS_BOT_PRIVATE_KEY }}
8883
- uses: actions/checkout@v5
8984
- uses: actions/setup-node@v6
9085
with:
@@ -106,13 +101,3 @@ jobs:
106101
GH_TOKEN: ${{ github.token }}
107102
run: |
108103
gh release create ${{ needs.check.outputs.VERSION }} --title "${{ needs.check.outputs.VERSION }}" --generate-notes --target ${{ github.sha }} ${{ (needs.check.outputs.RELEASE_CHANNEL != 'latest' && '--prerelease') || ''}}
109-
110-
- name: Install MCP Publisher
111-
run: |
112-
curl -L "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" | tar xz mcp-publisher
113-
114-
- name: Login to MCP Registry
115-
run: ./mcp-publisher login github --token ${{ steps.app-token.outputs.token }}
116-
117-
- name: Publish to MCP Registry
118-
run: ./mcp-publisher publish
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
---
2+
name: Publish to MCP Registry
3+
on:
4+
workflow_dispatch:
5+
6+
jobs:
7+
publish:
8+
runs-on: ubuntu-latest
9+
environment: Production
10+
permissions:
11+
contents: write
12+
id-token: write
13+
steps:
14+
- uses: GitHubSecurityLab/actions-permissions/monitor@v1
15+
- uses: actions/checkout@v5
16+
17+
- name: Install MCP Publisher
18+
run: |
19+
curl -L "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" | tar xz mcp-publisher
20+
21+
- name: Login to MCP Registry
22+
run: ./mcp-publisher login github-oidc
23+
24+
- name: Publish to MCP Registry
25+
run: ./mcp-publisher publish

package-lock.json

Lines changed: 16 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
"@ai-sdk/google": "^2.0.23",
6767
"@ai-sdk/openai": "^2.0.52",
6868
"@eslint/js": "^9.34.0",
69-
"@modelcontextprotocol/inspector": "^0.16.5",
69+
"@modelcontextprotocol/inspector": "^0.17.1",
7070
"@mongodb-js/oidc-mock-provider": "^0.11.3",
7171
"@redocly/cli": "^2.0.8",
7272
"@types/express": "^5.0.3",

scripts/generateArguments.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ function updateServerJsonEnvVars(envVars: EnvironmentVariable[]): void {
178178
version?: string;
179179
packages: {
180180
registryType?: string;
181-
identifier?: string;
181+
identifier: string;
182182
environmentVariables: EnvironmentVariable[];
183183
packageArguments?: unknown[];
184184
version?: string;
@@ -209,12 +209,13 @@ function updateServerJsonEnvVars(envVars: EnvironmentVariable[]): void {
209209
for (const pkg of serverJson.packages) {
210210
pkg.environmentVariables = envVarsArray as EnvironmentVariable[];
211211
pkg.packageArguments = packageArguments;
212-
pkg.version = version;
213212

214-
// Update OCI identifier version tag if this is an OCI package
215-
if (pkg.registryType === "oci" && pkg.identifier) {
213+
// For OCI packages, update the version tag in the identifier and not a version field
214+
if (pkg.registryType === "oci") {
216215
// Replace the version tag in the OCI identifier (e.g., docker.io/mongodb/mongodb-mcp-server:1.0.0)
217216
pkg.identifier = pkg.identifier.replace(/:[^:]+$/, `:${version}`);
217+
} else {
218+
pkg.version = version;
218219
}
219220
}
220221
}

server.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -637,8 +637,7 @@
637637
"description": "API key for Voyage AI embeddings service (required for vector search operations with text-to-embedding conversion).",
638638
"isRequired": false
639639
}
640-
],
641-
"version": "1.2.0"
640+
]
642641
}
643642
]
644643
}

src/common/search/embeddingsProvider.ts

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,33 @@ export const zVoyageModels = z
2727
.enum(["voyage-3-large", "voyage-3.5", "voyage-3.5-lite", "voyage-code-3"])
2828
.default("voyage-3-large");
2929

30+
// Zod does not undestand JS boxed numbers (like Int32) as integer literals,
31+
// so we preprocess them to unwrap them so Zod understands them.
32+
function unboxNumber(v: unknown): number {
33+
if (v && typeof v === "object" && typeof v.valueOf === "function") {
34+
const n = Number(v.valueOf());
35+
if (!Number.isNaN(n)) return n;
36+
}
37+
return v as number;
38+
}
39+
3040
export const zVoyageEmbeddingParameters = z.object({
3141
outputDimension: z
32-
.union([z.literal(256), z.literal(512), z.literal(1024), z.literal(2048), z.literal(4096)])
42+
.preprocess(
43+
unboxNumber,
44+
z.union([z.literal(256), z.literal(512), z.literal(1024), z.literal(2048), z.literal(4096)])
45+
)
3346
.optional()
3447
.default(1024),
35-
outputDType: z.enum(["float", "int8", "uint8", "binary", "ubinary"]).optional().default("float"),
48+
outputDtype: z.enum(["float", "int8", "uint8", "binary", "ubinary"]).optional().default("float"),
3649
});
3750

51+
const zVoyageAPIParameters = zVoyageEmbeddingParameters
52+
.extend({
53+
inputType: z.enum(["query", "document"]),
54+
})
55+
.strip();
56+
3857
type VoyageModels = z.infer<typeof zVoyageModels>;
3958
type VoyageEmbeddingParameters = z.infer<typeof zVoyageEmbeddingParameters> & EmbeddingParameters;
4059

@@ -62,11 +81,15 @@ class VoyageEmbeddingsProvider implements EmbeddingsProvider<VoyageModels, Voyag
6281
content: EmbeddingsInput[],
6382
parameters: VoyageEmbeddingParameters
6483
): Promise<Embeddings[]> {
84+
// This ensures that if we receive any random parameter from the outside (agent or us)
85+
// it's stripped before sending it to Voyage, as Voyage will reject the request on
86+
// a single unknown parameter.
87+
const voyage = zVoyageAPIParameters.parse(parameters);
6588
const model = this.voyage.textEmbeddingModel(modelId);
6689
const { embeddings } = await embedMany({
6790
model,
6891
values: content,
69-
providerOptions: { voyage: parameters },
92+
providerOptions: { voyage },
7093
});
7194

7295
return embeddings;

src/tools/mongodb/read/aggregate.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ const VectorSearchStage = z.object({
4747
filter: zEJSON()
4848
.optional()
4949
.describe(
50-
"MQL filter that can only use pre-filter fields from the index definition. Note to LLM: If unsure, use the `collection-indexes` tool to learn which fields can be used for pre-filtering."
50+
"MQL filter that can only use filter fields from the index definition. Note to LLM: If unsure, use the `collection-indexes` tool to learn which fields can be used for filtering."
5151
),
5252
embeddingParameters: zSupportedEmbeddingParameters
5353
.optional()
@@ -59,11 +59,21 @@ const VectorSearchStage = z.object({
5959
});
6060

6161
export const AggregateArgs = {
62-
pipeline: z
63-
.array(z.union([AnyStage, VectorSearchStage]))
64-
.describe(
65-
"An array of aggregation stages to execute. $vectorSearch can only appear as the first stage of the aggregation pipeline or as the first stage of a $unionWith subpipeline. When using $vectorSearch, unless the user explicitly asks for the embeddings, $unset any embedding field to avoid reaching context limits."
66-
),
62+
pipeline: z.array(z.union([AnyStage, VectorSearchStage])).describe(
63+
`An array of aggregation stages to execute.
64+
\`$vectorSearch\` **MUST** be the first stage of the pipeline, or the first stage of a \`$unionWith\` subpipeline.
65+
### Usage Rules for \`$vectorSearch\`
66+
- **Unset embeddings:**
67+
Unless the user explicitly requests the embeddings, add an \`$unset\` stage **at the end of the pipeline** to remove the embedding field and avoid context limits. **The $unset stage in this situation is mandatory**.
68+
- **Pre-filtering:**
69+
If the user requests additional filtering, include filters in \`$vectorSearch.filter\` only for pre-filter fields in the vector index.
70+
NEVER include fields in $vectorSearch.filter that are not part of the vector index.
71+
- **Post-filtering:**
72+
For all remaining filters, add a $match stage after $vectorSearch.
73+
### Note to LLM
74+
- If unsure which fields are filterable, use the collection-indexes tool to determine valid prefilter fields.
75+
- If no requested filters are valid prefilters, omit the filter key from $vectorSearch.`
76+
),
6777
responseBytesLimit: z.number().optional().default(ONE_MB).describe(`\
6878
The maximum number of bytes to return in the response. This value is capped by the server's configured maxBytesPerQuery and cannot be exceeded. \
6979
Note to LLM: If the entire aggregation result is required, use the "export" tool instead of increasing this limit.\

0 commit comments

Comments
 (0)