diff --git a/.changeset/config.json b/.changeset/config.json index cd1bcf04..2be13d43 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -7,5 +7,5 @@ "access": "public", "baseBranch": "main", "updateInternalDependencies": "patch", - "ignore": ["test-ui"] + "ignore": [] } diff --git a/BETA_RELEASES.md b/.github/BETA_RELEASES.md similarity index 100% rename from BETA_RELEASES.md rename to .github/BETA_RELEASES.md diff --git a/CHANGESET_WORKFLOW.md b/.github/CHANGESET_WORKFLOW.md similarity index 100% rename from CHANGESET_WORKFLOW.md rename to .github/CHANGESET_WORKFLOW.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 97daa34c..968a6578 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -12,11 +12,56 @@ Fixes # (issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) - [ ] Documentation update +- [ ] Internal change (refactoring, tests, tooling) + +## 📦 Changeset Required? + + + +**Does this PR need a changeset?** +- [ ] ✅ Yes - I have created a changeset (`pnpm changeset`) +- [ ] ❌ No - This is an internal-only change (docs, tests, tooling) + +**Quick reminder:** +```bash +pnpm changeset # Creates a changeset interactively +``` + +**📚 Full guide:** [Changeset Workflow Guide](.github/CHANGESET_WORKFLOW.md) +**Need help?** See [when to create changesets](.github/CHANGESET_WORKFLOW.md#-changeset-types) and [examples](.github/CHANGESET_WORKFLOW.md#-changeset-types) + +## 🚀 Release Target + +- [ ] `main` branch → Stable release (default) +- [ ] `beta` branch → Beta/prerelease version +- [ ] Other feature branch → No release + +**Releasing a beta?** See the [Beta Release Workflow Guide](.github/BETA_RELEASES.md) for instructions. ## Checklist +### Code Quality + - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my own code - [ ] I have added tests that prove my fix is effective or that my feature works +- [ ] Existing tests pass locally (`pnpm test`) +- [ ] Linting passes (`pnpm lint`) +- [ ] Build succeeds (`pnpm build`) + +### Documentation + - [ ] The title of my pull request follows the [conventional commits](https://www.conventionalcommits.org/) standard - [ ] Changes have been documented in the README/documentation (if applicable) +- [ ] Breaking changes are clearly documented with migration steps + +### Release Preparation + +- [ ] **I have created a changeset** (`pnpm changeset`) - if this affects published packages +- [ ] The changeset has a clear, user-focused description +- [ ] Version bump type is appropriate (patch/minor/major) +- [ ] All affected packages are included in the changeset + +### Additional Notes + + diff --git a/VERSIONING.md b/.github/VERSIONING.md similarity index 99% rename from VERSIONING.md rename to .github/VERSIONING.md index 2038bd96..6ee3a7c4 100644 --- a/VERSIONING.md +++ b/.github/VERSIONING.md @@ -216,7 +216,7 @@ If you want packages to always have the same version: ### Ignore Packages Packages already ignored (in `.changeset/config.json`): -- `test-ui` (test application, not published) +- add the package in `"ignore": []` ## CI/CD Integration @@ -299,7 +299,6 @@ Make sure all packages are in the workspace config (`pnpm-workspace.yaml`): ```yaml packages: - 'packages/*' - - 'test_app' ``` ### "Package is not published" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f64619fa..f0eb863e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -36,55 +36,14 @@ jobs: - name: Install Dependencies run: pnpm install - - name: Build Packages - run: pnpm build - - name: Create Release Pull Request or Publish to npm id: changesets uses: changesets/action@v1 with: - version: pnpm run version - commit: 'chore: version packages' - title: 'chore: version packages' + publish: pnpm release + version: pnpm version + commit: 'chore(release): version packages' + title: 'chore(release): version packages' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Publish mcp-use package with NPM_TOKEN - if: steps.changesets.outputs.hasChangesets == 'false' - run: | - echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > .npmrc - echo "📦 Publishing mcp-use with NPM_TOKEN..." - cd packages/mcp-use && pnpm publish --access public --no-git-checks - cd ../.. - rm -f .npmrc - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - - - name: Publish other packages with NPM_TOKEN_ORG - if: steps.changesets.outputs.hasChangesets == 'false' - run: | - echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN_ORG }}" > .npmrc - - # Publish in dependency order: inspector and create-mcp-use-app first, then cli - echo "📦 Publishing @mcp-use/inspector with NPM_TOKEN_ORG..." - cd packages/inspector && pnpm publish --access public --no-git-checks - cd ../.. - - echo "📦 Publishing create-mcp-use-app with NPM_TOKEN_ORG..." - cd packages/create-mcp-use-app && pnpm publish --access public --no-git-checks - cd ../.. - - echo "📦 Publishing @mcp-use/cli with NPM_TOKEN_ORG..." - cd packages/cli && pnpm publish --access public --no-git-checks - cd ../.. - - rm -f .npmrc - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN_ORG }} - - - name: Send Notification on Success - if: steps.changesets.outputs.hasChangesets == 'false' - run: | - echo "✅ Packages published successfully!" - echo "📦 mcp-use published with NPM_TOKEN" - echo "📦 Other packages published with NPM_TOKEN_ORG" + NPM_TOKEN: ${{ secrets.NPM_TOKEN_ORG }} diff --git a/.github/workflows/release_beta.yml b/.github/workflows/release_beta.yml index 1c1111e5..42fc80d8 100644 --- a/.github/workflows/release_beta.yml +++ b/.github/workflows/release_beta.yml @@ -36,62 +36,15 @@ jobs: - name: Install Dependencies run: pnpm install --no-frozen-lockfile - - name: Build Packages - run: pnpm build - - name: Create Release Pull Request or Publish to npm id: changesets uses: changesets/action@v1 with: - version: pnpm run version - commit: 'chore: version packages (beta)' - title: 'chore: version packages (beta)' + publish: pnpm release + version: pnpm version + commit: 'chore(release): version packages (beta)' + title: 'chore(release): version packages (beta)' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Publish mcp-use package with NPM_TOKEN (beta) - if: steps.changesets.outputs.hasChangesets == 'false' - run: | - echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > .npmrc - echo "📦 Publishing mcp-use@beta with NPM_TOKEN..." - cd packages/mcp-use && pnpm publish --access public --no-git-checks --tag beta - cd ../.. - rm -f .npmrc - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - - - name: Publish other packages with NPM_TOKEN_ORG (beta) - if: steps.changesets.outputs.hasChangesets == 'false' - run: | - echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN_ORG }}" > .npmrc - - # Publish in dependency order: inspector and create-mcp-use-app first, then cli - echo "📦 Publishing @mcp-use/inspector@beta with NPM_TOKEN_ORG..." - cd packages/inspector && pnpm publish --access public --no-git-checks --tag beta - cd ../.. - - echo "📦 Publishing create-mcp-use-app@beta with NPM_TOKEN_ORG..." - cd packages/create-mcp-use-app && pnpm publish --access public --no-git-checks --tag beta - cd ../.. - - echo "📦 Publishing @mcp-use/cli@beta with NPM_TOKEN_ORG..." - cd packages/cli && pnpm publish --access public --no-git-checks --tag beta - cd ../.. - - rm -f .npmrc - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN_ORG }} - - - name: Send Notification on Success - if: steps.changesets.outputs.hasChangesets == 'false' - run: | - echo "✅ Beta packages published successfully!" - echo "📦 mcp-use@beta published with NPM_TOKEN" - echo "📦 Other packages@beta published with NPM_TOKEN_ORG" - echo "" - echo "Install beta versions with:" - echo " npm install mcp-use@beta" - echo " npm install @mcp-use/cli@beta" - echo " npm install @mcp-use/inspector@beta" - echo " npm install create-mcp-use-app@beta" + NPM_TOKEN: ${{ secrets.NPM_TOKEN_ORG }} diff --git a/INSPECTOR_INTEGRATION.md b/INSPECTOR_INTEGRATION.md index 616c01a4..f1a7c336 100644 --- a/INSPECTOR_INTEGRATION.md +++ b/INSPECTOR_INTEGRATION.md @@ -33,7 +33,7 @@ The MCP Inspector is now automatically mounted at `/inspector` for all MCP serve When developers create a new MCP server: ```typescript -import { createMCPServer } from 'mcp-use' +import { createMCPServer } from 'mcp-use/server' const server = createMCPServer('my-server', { version: '1.0.0', @@ -121,26 +121,4 @@ For published packages: - `packages/mcp-use/package.json` - Added inspector as optional peer dependency - `packages/create-mcp-use-app/src/templates/ui/package.json` - Added inspector dependency - `packages/create-mcp-use-app/src/templates/ui/src/server.ts` - Updated comments -- `test_app/package.json` - Added inspector dependency -- `test_app/src/server.ts` - Updated comments - -## Testing - -To test the integration: - -1. Build all packages: - ```bash - cd /Users/e.t./Projects/mcp-use/mcp-use-ts - pnpm install - cd packages/inspector && pnpm build - cd ../mcp-use && pnpm build - ``` - -2. Run the test app: - ```bash - cd test_app - pnpm dev - ``` - -3. Open `http://localhost:3000/inspector` in your browser diff --git a/package.json b/package.json index d90066d7..e9278a44 100644 --- a/package.json +++ b/package.json @@ -4,8 +4,7 @@ "private": true, "type": "module", "workspaces": [ - "packages/*", - "test_app" + "packages/*" ], "scripts": { "build": "pnpm run build:mcp-use && pnpm run build:other", diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index f87f8f9f..a7397642 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,14 @@ # @mcp-use/cli +## 2.1.3 + +### Patch Changes + +- 5b470a3: fix: export server stuff from mcp-use/server instead of root +- Updated dependencies [5b470a3] + - @mcp-use/inspector@0.3.3 + - mcp-use@1.0.1 + ## 2.1.2 ### Patch Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index 69d76c82..ba8ec27f 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@mcp-use/cli", - "version": "2.1.2", + "version": "2.1.3", "description": "Build tool for MCP UI widgets - bundles React components into standalone HTML pages for Model Context Protocol servers", "author": "mcp-use, Inc.", "license": "MIT", diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 45cb1067..a4a61b55 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -2,21 +2,27 @@ import { Command } from 'commander'; import { buildWidgets } from './build'; import { spawn } from 'node:child_process'; -import { promises as fs } from 'node:fs'; +import { readFileSync } from 'node:fs'; +import { access } from 'node:fs/promises'; import path from 'node:path'; import open from 'open'; - const program = new Command(); + +const packageContent = readFileSync(path.join(__dirname, '../package.json'), 'utf-8') +const packageJson = JSON.parse(packageContent) +const packageVersion = packageJson.version || 'unknown' + + program .name('mcp-use') .description('MCP CLI tool') - .version('2.0.1'); + .version(packageVersion); // Helper to check if port is available async function isPortAvailable(port: number): Promise { try { - const response = await fetch(`http://localhost:${port}`); + await fetch(`http://localhost:${port}`); return false; // Port is in use } catch { return true; // Port is available @@ -77,7 +83,7 @@ program try { const projectPath = path.resolve(options.path); - console.log('\x1b[36m\x1b[1mmcp-use\x1b[0m \x1b[90mVersion: 2.0.1\x1b[0m\n'); + console.log(`\x1b[36m\x1b[1mmcp-use\x1b[0m \x1b[90mVersion: ${packageJson.version}\x1b[0m\n`); // Run tsc first console.log('Building TypeScript...'); @@ -103,7 +109,7 @@ program const projectPath = path.resolve(options.path); let port = parseInt(options.port, 10); - console.log('\x1b[36m\x1b[1mmcp-use\x1b[0m \x1b[90mVersion: 2.0.1\x1b[0m\n'); + console.log(`\x1b[36m\x1b[1mmcp-use\x1b[0m \x1b[90mVersion: ${packageJson.version}\x1b[0m\n`); // Check if port is available, find alternative if needed if (!(await isPortAvailable(port))) { @@ -114,11 +120,11 @@ program } // Find the main source file - let serverFile = 'src/server.ts'; + let serverFile = 'index.ts'; try { - await fs.access(path.join(projectPath, serverFile)); + await access(path.join(projectPath, serverFile)); } catch { - serverFile = 'src/index.ts'; + serverFile = 'src/server.ts'; } // Start all processes concurrently @@ -149,25 +155,11 @@ program // 3. Server with tsx const serverProc = spawn('npx', ['tsx', 'watch', serverFile], { cwd: projectPath, - stdio: 'pipe', + stdio: 'inherit', shell: false, env: { ...process.env, PORT: String(port) }, }); - // Handle server errors gracefully - serverProc.stderr?.on('data', (data) => { - const output = data.toString(); - if (output.includes('EADDRINUSE')) { - console.log(`\x1b[31m✗\x1b[0m Port ${port} is still in use. Please try a different port with --port`); - console.log(`\x1b[90mHint: Use --port 3001 or kill the process using port ${port}\x1b[0m`); - process.exit(1); - } - }); - - serverProc.stdout?.on('data', (data) => { - process.stdout.write(data); - }); - processes.push(serverProc); // Auto-open inspector if enabled @@ -215,14 +207,14 @@ program const projectPath = path.resolve(options.path); const port = parseInt(options.port, 10); - console.log('\x1b[36m\x1b[1mmcp-use\x1b[0m \x1b[90mVersion: 2.0.1\x1b[0m\n'); + console.log(`\x1b[36m\x1b[1mmcp-use\x1b[0m \x1b[90mVersion: ${packageJson.version}\x1b[0m\n`); // Find the built server file - let serverFile = 'dist/server.js'; + let serverFile = 'dist/index.js'; try { - await fs.access(path.join(projectPath, serverFile)); + await access(path.join(projectPath, serverFile)); } catch { - serverFile = 'dist/index.js'; + serverFile = 'dist/server.js'; } console.log('Starting production server...'); diff --git a/packages/create-mcp-use-app/CHANGELOG.md b/packages/create-mcp-use-app/CHANGELOG.md index ab0f728b..beb833e5 100644 --- a/packages/create-mcp-use-app/CHANGELOG.md +++ b/packages/create-mcp-use-app/CHANGELOG.md @@ -1,5 +1,11 @@ # create-mcp-use-app +## 0.3.2 + +### Patch Changes + +- 5b470a3: fix: export server stuff from mcp-use/server instead of root + ## 0.3.1 ### Patch Changes diff --git a/packages/create-mcp-use-app/package.json b/packages/create-mcp-use-app/package.json index 9840505f..6f5dfec5 100644 --- a/packages/create-mcp-use-app/package.json +++ b/packages/create-mcp-use-app/package.json @@ -1,6 +1,6 @@ { "name": "create-mcp-use-app", - "version": "0.3.1", + "version": "0.3.2", "type": "module", "description": "Create MCP-Use apps with one command", "author": "mcp-use, Inc.", @@ -32,7 +32,7 @@ "scripts": { "build": "npm run clean && tsup src/index.ts --format esm && tsc --emitDeclarationOnly --declaration && npm run copy-templates", "clean": "rm -rf dist tsconfig.tsbuildinfo", - "copy-templates": "mkdir -p dist/templates && cp -r src/templates/* dist/templates/", + "copy-templates": "node scripts/copy-templates.js", "dev": "tsc --build --watch", "test": "vitest", "lint": "eslint ." diff --git a/packages/create-mcp-use-app/scripts/copy-templates.js b/packages/create-mcp-use-app/scripts/copy-templates.js new file mode 100644 index 00000000..98a7d4fa --- /dev/null +++ b/packages/create-mcp-use-app/scripts/copy-templates.js @@ -0,0 +1,47 @@ +#!/usr/bin/env node + +import { promises as fs } from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +const sourceDir = path.join(__dirname, '..', 'src', 'templates'); +const targetDir = path.join(__dirname, '..', 'dist', 'templates'); + +async function copyDir(src, dest, excludeDirs = ['node_modules']) { + try { + await fs.mkdir(dest, { recursive: true }); + + const entries = await fs.readdir(src, { withFileTypes: true }); + + for (const entry of entries) { + const srcPath = path.join(src, entry.name); + const destPath = path.join(dest, entry.name); + + // Skip excluded directories + if (entry.isDirectory() && excludeDirs.includes(entry.name)) { + console.log(`Skipping ${entry.name}/`); + continue; + } + + if (entry.isDirectory()) { + await copyDir(srcPath, destPath, excludeDirs); + } else { + await fs.copyFile(srcPath, destPath); + console.log(`Copied ${entry.name}`); + } + } + } catch (error) { + console.error('Error copying templates:', error); + process.exit(1); + } +} + +// Ensure target directory exists +await fs.mkdir(targetDir, { recursive: true }); + +console.log('Copying templates...'); +await copyDir(sourceDir, targetDir); +console.log('Templates copied successfully!'); diff --git a/packages/create-mcp-use-app/src/index.ts b/packages/create-mcp-use-app/src/index.ts index 5a0c6b0d..3f9f58d8 100644 --- a/packages/create-mcp-use-app/src/index.ts +++ b/packages/create-mcp-use-app/src/index.ts @@ -12,14 +12,97 @@ const __dirname = dirname(__filename) const program = new Command() +const packageJson = JSON.parse( + readFileSync(join(__dirname, '../package.json'), 'utf-8') +) + +// Read current package versions from workspace +function getCurrentPackageVersions() { + const versions: Record = {} + + try { + // Try multiple possible workspace root locations + const possibleRoots = [ + resolve(__dirname, '../../../..'), // From dist/templates + resolve(__dirname, '../../../../..'), // From dist + resolve(process.cwd(), '.'), // Current working directory + resolve(process.cwd(), '..'), // Parent of current directory + ] + + let workspaceRoot = null + for (const root of possibleRoots) { + if (existsSync(join(root, 'packages/mcp-use/package.json'))) { + workspaceRoot = root + break + } + } + + if (!workspaceRoot) { + throw new Error('Workspace root not found') + } + + // Read mcp-use version + const mcpUsePackage = JSON.parse( + readFileSync(join(workspaceRoot, 'packages/mcp-use/package.json'), 'utf-8') + ) + versions['mcp-use'] = mcpUsePackage.version + + // Read cli version + const cliPackage = JSON.parse( + readFileSync(join(workspaceRoot, 'packages/cli/package.json'), 'utf-8') + ) + versions['@mcp-use/cli'] = cliPackage.version + + // Read inspector version + const inspectorPackage = JSON.parse( + readFileSync(join(workspaceRoot, 'packages/inspector/package.json'), 'utf-8') + ) + versions['@mcp-use/inspector'] = inspectorPackage.version + } catch (error) { + console.warn('⚠️ Could not read workspace package versions, using defaults') + console.warn(` Error: ${error}`) + } + + return versions +} + +// Process template files to replace version placeholders +function processTemplateFile(filePath: string, versions: Record, isDevelopment: boolean = false) { + const content = readFileSync(filePath, 'utf-8') + let processedContent = content + + // Replace version placeholders with current versions + for (const [packageName, version] of Object.entries(versions)) { + const placeholder = `{{${packageName}_version}}` + const versionPrefix = isDevelopment ? 'workspace:*' : `^${version}` + processedContent = processedContent.replace(new RegExp(placeholder, 'g'), versionPrefix) + } + + // Handle workspace dependencies based on mode + if (isDevelopment) { + // Keep workspace dependencies for development + processedContent = processedContent.replace(/"mcp-use": "\^[^"]+"/, '"mcp-use": "workspace:*"') + processedContent = processedContent.replace(/"@mcp-use\/cli": "\^[^"]+"/, '"@mcp-use/cli": "workspace:*"') + processedContent = processedContent.replace(/"@mcp-use\/inspector": "\^[^"]+"/, '"@mcp-use/inspector": "workspace:*"') + } else { + // Replace workspace dependencies with specific versions for production + processedContent = processedContent.replace(/"mcp-use": "workspace:\*"/, `"mcp-use": "^${versions['mcp-use'] || '1.0.0'}"`) + processedContent = processedContent.replace(/"@mcp-use\/cli": "workspace:\*"/, `"@mcp-use/cli": "^${versions['@mcp-use/cli'] || '2.0.0'}"`) + processedContent = processedContent.replace(/"@mcp-use\/inspector": "workspace:\*"/, `"@mcp-use/inspector": "^${versions['@mcp-use/inspector'] || '0.3.0'}"`) + } + + return processedContent +} + program .name('create-mcp-use-app') .description('Create a new MCP server project') - .version('0.1.0') + .version(packageJson.version) .argument('[project-name]', 'Name of the MCP server project') .option('-t, --template