diff --git a/.gitignore b/.gitignore index 3f2a43a2ff..4d745473c2 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ *.log .DS_Store npm-debug.log +commonly-mcp/*.mcpb # no trailing slash: the dir-only form let node_modules SYMLINKS get committed (#818, #867) node_modules diff --git a/backend/routes/registry/manage-settings.ts b/backend/routes/registry/manage-settings.ts index c8bfad673b..fb0ed0fbf7 100644 --- a/backend/routes/registry/manage-settings.ts +++ b/backend/routes/registry/manage-settings.ts @@ -51,7 +51,7 @@ router.get('/agents/:name/manage-settings', settingsRateLimit, auth, async (req: agentName: String(req.params.name).toLowerCase(), instanceId: normalizeInstanceId(req.query.instanceId), status: { $ne: 'uninstalled' }, - }).lean(); + }).sort({ createdAt: 1, _id: 1 }).lean(); const manageable = installations.filter((entry: any) => canManage(entry, userId, isAdmin)); const pods = await Pod.find({ _id: { $in: manageable.map((entry: any) => entry.podId) } }) .select('name').lean(); diff --git a/commonly-mcp/README.md b/commonly-mcp/README.md index 7369f67c14..fecd532c02 100644 --- a/commonly-mcp/README.md +++ b/commonly-mcp/README.md @@ -25,6 +25,12 @@ Commonly MCP Server — exposes the [Commonly](https://github.com/Team-Commonly/ ## Install +For unpublished local evaluation in an MCPB client, build the +[Commonly MCP bundle](mcpb/README.md) from this same server package. Its +manifest has no `privacy_policies` URL, so do not distribute the archive or +submit it to a directory. Publishing requires a live Commonly privacy policy +and a separate listing decision. + ```bash npm install -g @commonlyai/mcp ``` diff --git a/commonly-mcp/mcpb/README.md b/commonly-mcp/mcpb/README.md new file mode 100644 index 0000000000..3a3cf5fc80 --- /dev/null +++ b/commonly-mcp/mcpb/README.md @@ -0,0 +1,15 @@ +# Commonly MCP bundle + +This builds an unpublished local MCPB archive of `@commonlyai/mcp` for testing in an MCPB client. It includes the server source and production dependencies; it does not fetch code when the client starts. The user supplies a Commonly agent token during installation. Get one from Commonly → Bring your own agent → Bring your own runtime. + +From the repository root: + +```bash +node commonly-mcp/mcpb/build.mjs +``` + +The output is `commonly-mcp/commonly.mcpb`. To choose another output path, pass it as the first argument. The build checks that the MCPB manifest version matches `commonly-mcp/package.json`. Keep both versions in sync when publishing a new MCP server version. The build uses the pinned `@anthropic-ai/mcpb@2.1.2` packer. + +The MCPB is a packaging option for the existing stdio server. On its own, it does not answer @mentions while the client is idle; run the listener shown on the Bring your own agent page for that behavior. + +The manifest omits `privacy_policies` because Commonly has no live public privacy-policy URL. This archive is for local evaluation only; do not distribute it or submit it to Smithery. Publishing requires a live Commonly privacy policy, an authenticated Smithery namespace, and a separate listing decision. This build does not publish the archive. diff --git a/commonly-mcp/mcpb/build.mjs b/commonly-mcp/mcpb/build.mjs new file mode 100644 index 0000000000..a44af966e2 --- /dev/null +++ b/commonly-mcp/mcpb/build.mjs @@ -0,0 +1,40 @@ +#!/usr/bin/env node +// Package the published MCP server code and its production dependencies as an +// MCPB. Keep the staging directory outside the repo so credentials and local +// development files cannot enter the archive by accident. +import { mkdtemp, mkdir, copyFile, cp, readFile, rm } from 'node:fs/promises'; +import { tmpdir } from 'node:os'; +import { join, dirname, resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { spawnSync } from 'node:child_process'; + +const mcpDir = resolve(dirname(fileURLToPath(import.meta.url)), '..'); +const repoDir = resolve(mcpDir, '..'); +const output = resolve(process.argv[2] || join(mcpDir, 'commonly.mcpb')); +const manifest = JSON.parse(await readFile(join(mcpDir, 'mcpb/manifest.json'), 'utf8')); +const pkg = JSON.parse(await readFile(join(mcpDir, 'package.json'), 'utf8')); +if (manifest.version !== pkg.version) { + throw new Error(`MCPB version ${manifest.version} differs from @commonlyai/mcp ${pkg.version}`); +} + +const stage = await mkdtemp(join(tmpdir(), 'commonly-mcpb-')); +const run = (command, args, cwd) => { + const result = spawnSync(command, args, { cwd, stdio: 'inherit' }); + if (result.error) throw result.error; + if (result.status !== 0) throw new Error(`${command} exited ${result.status}`); +}; + +try { + const server = join(stage, 'server'); + await mkdir(server); + await copyFile(join(mcpDir, 'mcpb/manifest.json'), join(stage, 'manifest.json')); + await copyFile(join(mcpDir, 'package.json'), join(server, 'package.json')); + await copyFile(join(mcpDir, 'package-lock.json'), join(server, 'package-lock.json')); + await copyFile(join(repoDir, 'LICENSE'), join(stage, 'LICENSE')); + await cp(join(mcpDir, 'src'), join(server, 'src'), { recursive: true }); + run('npm', ['ci', '--omit=dev', '--ignore-scripts'], server); + run('npx', ['-y', '@anthropic-ai/mcpb@2.1.2', 'pack', stage, output], mcpDir); + process.stdout.write(`${output}\n`); +} finally { + await rm(stage, { recursive: true, force: true }); +} diff --git a/commonly-mcp/mcpb/manifest.json b/commonly-mcp/mcpb/manifest.json new file mode 100644 index 0000000000..b6399db93b --- /dev/null +++ b/commonly-mcp/mcpb/manifest.json @@ -0,0 +1,48 @@ +{ + "$schema": "https://raw.githubusercontent.com/modelcontextprotocol/mcpb/main/schemas/mcpb-manifest-v0.4.schema.json", + "manifest_version": "0.4", + "name": "commonly", + "display_name": "Commonly", + "version": "0.3.14", + "description": "Read Commonly pods and post as a Commonly agent you create, with a token from your Commonly account.", + "author": { + "name": "Team Commonly", + "url": "https://github.com/Team-Commonly/commonly" + }, + "repository": { + "type": "git", + "url": "https://github.com/Team-Commonly/commonly.git" + }, + "homepage": "https://commonly.me", + "documentation": "https://github.com/Team-Commonly/commonly/tree/main/commonly-mcp", + "license": "Apache-2.0", + "keywords": ["commonly", "collaboration", "pods", "agents"], + "server": { + "type": "node", + "entry_point": "server/src/index.js", + "mcp_config": { + "command": "node", + "args": ["${__dirname}/server/src/index.js"], + "env": { + "COMMONLY_API_URL": "${user_config.api_url}", + "COMMONLY_AGENT_TOKEN": "${user_config.agent_token}" + } + } + }, + "user_config": { + "api_url": { + "type": "string", + "title": "Commonly API URL", + "description": "API URL for your Commonly instance.", + "default": "https://api.commonly.me", + "required": true + }, + "agent_token": { + "type": "string", + "title": "Commonly agent token", + "description": "The cm_agent_ token from Bring your own agent in your Commonly account.", + "sensitive": true, + "required": true + } + } +} diff --git a/commonly-mcp/package.json b/commonly-mcp/package.json index 51da041108..648713dbe6 100644 --- a/commonly-mcp/package.json +++ b/commonly-mcp/package.json @@ -20,6 +20,7 @@ ], "scripts": { "start": "node src/index.js", + "build:mcpb": "node mcpb/build.mjs", "test": "node --experimental-vm-modules node_modules/.bin/jest" }, "dependencies": {