豆豆友情提示:这是一个非官方 GitHub 代理镜像,主要用于网络测试或访问加速。请勿在此进行登录、注册或处理任何敏感信息。进行这些操作请务必访问官方网站 github.com。 Raw 内容也通过此代理提供。
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions .github/workflows/pre-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ name: Pre-release
permissions: read-all

on:
workflow_dispatch:
push:
branches:
- release-please-*
Expand All @@ -23,10 +24,5 @@ jobs:
cache: npm
node-version-file: '.nvmrc'

- name: Install MCP Publisher
run: |
export OS=$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
curl -L "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_${OS}.tar.gz" | tar xz mcp-publisher

- name: Verify server.json
run: npm run verify-server-json-version
5 changes: 3 additions & 2 deletions GEMINI.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Instructions

- use `npm run build` to run tsc and test build
- use `npm run test` to run tests, run all tests to verify correctness
- use `npm run build` to run tsc and test build.
- use `npm run test` to run tests, run all tests to verify correctness.
- use only scripts from `package.json` to run commands.
1 change: 1 addition & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export default defineConfig([
name: 'TypeScript rules',
rules: {
'@local/check-license': 'error',
curly: ['error', 'all'],
Comment thread
OrKoN marked this conversation as resolved.

'no-undef': 'off',
'no-unused-vars': 'off',
Expand Down
40 changes: 30 additions & 10 deletions scripts/generate-docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,15 +213,23 @@ function getZodTypeInfo(schema: ZodSchema): TypeInfo {
defaultValue = def.defaultValue();
}
const next = def.innerType || def.schema;
if (!next) break;
if (!next) {
break;
}
schema = next;
def = schema._def;
if (!description && schema.description) description = schema.description;
if (!description && schema.description) {
description = schema.description;
}
}

const result: TypeInfo = {type: 'unknown'};
if (description) result.description = description;
if (defaultValue !== undefined) result.default = defaultValue;
if (description) {
result.description = description;
}
if (defaultValue !== undefined) {
result.default = defaultValue;
}

switch (def.typeName) {
case 'ZodString':
Expand Down Expand Up @@ -254,7 +262,9 @@ function getZodTypeInfo(schema: ZodSchema): TypeInfo {
function isRequired(schema: ZodSchema): boolean {
let def = schema._def;
while (def.typeName === 'ZodEffects') {
if (!def.schema) break;
if (!def.schema) {
break;
}
schema = def.schema;
def = schema._def;
}
Expand Down Expand Up @@ -325,9 +335,15 @@ async function generateToolDocumentation(): Promise<void> {
const aIndex = categoryOrder.indexOf(a);
const bIndex = categoryOrder.indexOf(b);
// Put known categories first, unknown categories last
if (aIndex === -1 && bIndex === -1) return a.localeCompare(b);
if (aIndex === -1) return 1;
if (bIndex === -1) return -1;
if (aIndex === -1 && bIndex === -1) {
return a.localeCompare(b);
}
if (aIndex === -1) {
return 1;
}
if (bIndex === -1) {
return -1;
}
return aIndex - bIndex;
});

Expand Down Expand Up @@ -386,8 +402,12 @@ async function generateToolDocumentation(): Promise<void> {
const propertyNames = Object.keys(properties).sort((a, b) => {
const aRequired = required.includes(a);
const bRequired = required.includes(b);
if (aRequired && !bRequired) return -1;
if (!aRequired && bRequired) return 1;
if (aRequired && !bRequired) {
return -1;
}
if (!aRequired && bRequired) {
return 1;
}
return a.localeCompare(b);
});
for (const propName of propertyNames) {
Expand Down
79 changes: 60 additions & 19 deletions scripts/verify-server-json-version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,72 @@

import {execSync} from 'node:child_process';
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';

const serverJsonFilePath = './server.json';
const serverJsonFilePath = path.join(process.cwd(), 'server.json');
Comment thread
OrKoN marked this conversation as resolved.
const serverJson = JSON.parse(fs.readFileSync(serverJsonFilePath, 'utf-8'));
fs.unlinkSync(serverJsonFilePath);

// Create the new server.json
execSync('./mcp-publisher init');
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mcp-verify-'));

const newServerJson = JSON.parse(fs.readFileSync(serverJsonFilePath, 'utf-8'));

const propertyToVerify = ['$schema'];
const diffProps = [];
try {
const osName = os.platform();
const arch = os.arch();
let platform = '';
if (osName === 'darwin') {
platform = 'darwin';
} else if (osName === 'linux') {
platform = 'linux';
}
// mcp-publisher does not support windows
else {
throw new Error(`Unsupported platform: ${osName}`);
}

for (const prop of propertyToVerify) {
if (serverJson[prop] !== newServerJson[prop]) {
diffProps.push(prop);
let archName = '';
if (arch === 'x64') {
archName = 'amd64';
} else if (arch === 'arm64') {
archName = 'arm64';
} else {
throw new Error(`Unsupported architecture: ${arch}`);
}
}

fs.writeFileSync('./server.json', JSON.stringify(serverJson, null, 2));
const osArch = `${platform}_${archName}`;
const binName = 'mcp-publisher';
const downloadUrl = `https://github.com/modelcontextprotocol/registry/releases/latest/download/${binName}_${osArch}.tar.gz`;

console.log(`Downloading ${binName} from ${downloadUrl}`);
const downloadCmd = `curl -L "${downloadUrl}" | tar xz -C "${tmpDir}" ${binName}`;
execSync(downloadCmd, {stdio: 'inherit'});

const publisherPath = path.join(tmpDir, binName);
fs.chmodSync(publisherPath, 0o755);
console.log(`Downloaded to ${publisherPath}`);

if (diffProps.length) {
throw new Error(
`The following props did not match the latest init value:\n${diffProps.map(
prop => `- "${prop}": "${newServerJson[prop]}"`,
)}`,
);
// Create the new server.json in the temporary directory
execSync(`${publisherPath} init`, {cwd: tmpDir, stdio: 'inherit'});

const newServerJsonPath = path.join(tmpDir, 'server.json');
const newServerJson = JSON.parse(fs.readFileSync(newServerJsonPath, 'utf-8'));

const propertyToVerify = ['$schema'];
const diffProps = [];

for (const prop of propertyToVerify) {
if (serverJson[prop] !== newServerJson[prop]) {
diffProps.push(prop);
}
}

if (diffProps.length) {
throw new Error(
`The following props in ${serverJsonFilePath} did not match the latest init value:\n${diffProps.map(
prop =>
`- "${prop}": expected "${newServerJson[prop]}", got "${serverJson[prop]}"`,
)}`,
);
}
} finally {
fs.rmSync(tmpDir, {recursive: true, force: true});
}
2 changes: 1 addition & 1 deletion server.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-10-17/server.schema.json",
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
"name": "io.github.ChromeDevTools/chrome-devtools-mcp",
"title": "Chrome DevTools MCP",
"description": "MCP server for Chrome DevTools",
Expand Down
7 changes: 5 additions & 2 deletions src/McpResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -259,10 +259,11 @@ export class McpResponse implements Response {
};
} else if (message instanceof DevTools.AggregatedIssue) {
const mappedIssueMessage = mapIssueToMessageObject(message);
if (!mappedIssueMessage)
if (!mappedIssueMessage) {
throw new Error(
"Can't provide detals for the msgid " + consoleMessageStableId,
);
}
consoleData = {
consoleMessageStableId,
...mappedIssueMessage,
Expand Down Expand Up @@ -321,7 +322,9 @@ export class McpResponse implements Response {
}
if (item instanceof DevTools.AggregatedIssue) {
const mappedIssueMessage = mapIssueToMessageObject(item);
if (!mappedIssueMessage) return null;
if (!mappedIssueMessage) {
return null;
}
return {
consoleMessageStableId,
...mappedIssueMessage,
Expand Down
20 changes: 15 additions & 5 deletions src/formatters/consoleFormatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ export function formatIssue(
if (processedMarkdown?.startsWith('# ')) {
processedMarkdown = processedMarkdown.substring(2).trimStart();
}
if (processedMarkdown) result.push(processedMarkdown);
if (processedMarkdown) {
result.push(processedMarkdown);
}

const links = issue.getDescription()?.links;
if (links && links.length > 0) {
Expand All @@ -102,7 +104,9 @@ export function formatIssue(
}> = [];
for (const singleIssue of issues) {
const details = singleIssue.details();
if (!details) continue;
if (!details) {
continue;
}

// We send the remaining details as untyped JSON because the DevTools
// frontend code is currently not re-usable.
Expand Down Expand Up @@ -152,17 +156,23 @@ export function formatIssue(
result.push(
...affectedResources.map(item => {
const details = [];
if (item.uid) details.push(`uid=${item.uid}`);
if (item.uid) {
details.push(`uid=${item.uid}`);
}
if (item.request) {
details.push(
(typeof item.request === 'number' ? `reqid=` : 'url=') + item.request,
);
}
if (item.data) details.push(`data=${JSON.stringify(item.data)}`);
if (item.data) {
details.push(`data=${JSON.stringify(item.data)}`);
}
return details.join(' ');
}),
);
if (result.length === 0) return 'No affected resources found';
if (result.length === 0) {
return 'No affected resources found';
}
return result.join('\n');
}

Expand Down