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
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ jobs:
- name: Build
run: pnpm build

- name: Lint
run: pnpm lint
- name: Lint + format check
run: pnpm lint:ci

- name: Typecheck
run: pnpm typecheck
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/cli-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm --filter @nimblebrain/mpak... build
- run: pnpm --filter @nimblebrain/mpak lint
- run: pnpm lint
- run: pnpm --filter @nimblebrain/mpak typecheck
- run: pnpm --filter @nimblebrain/mpak test

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/schemas-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm --filter @nimblebrain/mpak-schemas build
- run: pnpm --filter @nimblebrain/mpak-schemas lint
- run: pnpm lint
- run: pnpm --filter @nimblebrain/mpak-schemas typecheck
- run: pnpm --filter @nimblebrain/mpak-schemas test

Expand Down
5 changes: 1 addition & 4 deletions .github/workflows/sdk-typescript-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,7 @@ jobs:
run: pnpm --filter @nimblebrain/mpak-sdk... build

- name: Lint
run: pnpm --filter @nimblebrain/mpak-sdk lint

- name: Format check
run: pnpm --filter @nimblebrain/mpak-sdk exec prettier --check "src/**/*.ts" "tests/**/*.ts"
run: pnpm lint

- name: Typecheck
run: pnpm --filter @nimblebrain/mpak-sdk typecheck
Expand Down
3 changes: 1 addition & 2 deletions .github/workflows/sdk-typescript-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ jobs:
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm --filter @nimblebrain/mpak-sdk... build
- run: pnpm --filter @nimblebrain/mpak-sdk lint
- run: pnpm --filter @nimblebrain/mpak-sdk exec prettier --check "src/**/*.ts" "tests/**/*.ts"
- run: pnpm lint
- run: pnpm --filter @nimblebrain/mpak-sdk typecheck
- run: pnpm --filter @nimblebrain/mpak-sdk test

Expand Down
7 changes: 0 additions & 7 deletions .prettierignore

This file was deleted.

7 changes: 0 additions & 7 deletions .prettierrc

This file was deleted.

3 changes: 2 additions & 1 deletion apps/docs/astro.config.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// @ts-check
import { defineConfig } from 'astro/config';

import starlight from '@astrojs/starlight';
import { defineConfig } from 'astro/config';

// https://astro.build/config
export default defineConfig({
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/src/components/Header.astro
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
import type { Props } from '@astrojs/starlight/props';
// biome-ignore lint/correctness/noUnusedImports: rendered as <Default> in the template below, which biome doesn't parse
import Default from '@astrojs/starlight/components/Header.astro';
---

Expand Down
2 changes: 1 addition & 1 deletion apps/docs/src/content.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ import { docsLoader } from '@astrojs/starlight/loaders';
import { docsSchema } from '@astrojs/starlight/schema';

export const collections = {
docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }),
docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }),
};
10 changes: 5 additions & 5 deletions apps/docs/src/styles/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
--sl-color-accent-high: hsl(38, 90%, 75%);
}

:root[data-theme='light'] {
:root[data-theme="light"] {
/* Gold accent for light mode - darker for readability on white */
--sl-color-accent-high: hsl(38, 92%, 28%);
--sl-color-accent: hsl(38, 92%, 40%);
Expand All @@ -21,8 +21,8 @@

/* Fonts */
:root {
--sl-font: 'Space Grotesk', var(--sl-font-system);
--sl-font-mono: 'JetBrains Mono', var(--sl-font-system-mono);
--sl-font: "Space Grotesk", var(--sl-font-system);
--sl-font-mono: "JetBrains Mono", var(--sl-font-system-mono);
}

/* Browse Registry button */
Expand All @@ -44,11 +44,11 @@
background-color: var(--sl-color-accent-high);
}

:root[data-theme='light'] .browse-registry-btn {
:root[data-theme="light"] .browse-registry-btn {
color: white;
}

:root[data-theme='light'] .browse-registry-btn:hover {
:root[data-theme="light"] .browse-registry-btn:hover {
background-color: var(--sl-color-accent-high);
color: white;
}
1 change: 0 additions & 1 deletion apps/registry/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
"test": "vitest run",
"test:watch": "vitest",
"test:coverage": "vitest run --coverage",
"lint": "eslint src",
"typecheck": "npm run db:generate && tsc --noEmit",
"db:generate": "prisma generate",
"db:migrate": "dotenv -e .env -- prisma migrate dev",
Expand Down
2 changes: 1 addition & 1 deletion apps/registry/prisma.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ export default defineConfig({
schema: path.join(__dirname, 'prisma', 'schema.prisma'),

datasource: {
url: process.env['DIRECT_URL'] || process.env['DATABASE_URL']!,
url: process.env.DIRECT_URL || process.env.DATABASE_URL!,
},
});
86 changes: 64 additions & 22 deletions apps/registry/prisma/seed.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/** biome-ignore-all lint/suspicious/noTemplateCurlyInString: intentional mpak manifest placeholders (${var} substituted at install time) */
/**
* Database Seed Script
*
Expand All @@ -13,19 +14,19 @@
*/

import 'dotenv/config';
import { PrismaClient } from '@prisma/client';
import { createHash } from 'node:crypto';
import { mkdir, writeFile } from 'node:fs/promises';
import { dirname, join } from 'node:path';
import { PrismaPg } from '@prisma/adapter-pg';
import { PrismaClient } from '@prisma/client';
import pg from 'pg';
import { createHash, randomUUID } from 'crypto';
import { mkdir, writeFile } from 'fs/promises';
import { dirname, join } from 'path';

// ---------------------------------------------------------------------------
// Database setup (standalone, doesn't use the app's singleton)
// ---------------------------------------------------------------------------

const pool = new pg.Pool({
connectionString: process.env['DATABASE_URL'],
connectionString: process.env.DATABASE_URL,
});

const adapter = new PrismaPg(pool);
Expand Down Expand Up @@ -590,7 +591,11 @@ const PACKAGES: SeedPackage[] = [
releaseUrl:
'https://github.com/NimbleBrainInc/mcp-server-nationalparks/releases/tag/v0.1.1',
manifest: nationalparksManifest('0.1.1'),
artifacts: multiPlatformArtifacts('NimbleBrainInc/mcp-server-nationalparks', '0.1.1', 82_000),
artifacts: multiPlatformArtifacts(
'NimbleBrainInc/mcp-server-nationalparks',
'0.1.1',
82_000,
),
},
{
version: '0.1.2',
Expand All @@ -603,7 +608,11 @@ const PACKAGES: SeedPackage[] = [
releaseUrl:
'https://github.com/NimbleBrainInc/mcp-server-nationalparks/releases/tag/v0.1.2',
manifest: nationalparksManifest('0.1.2'),
artifacts: multiPlatformArtifacts('NimbleBrainInc/mcp-server-nationalparks', '0.1.2', 83_000),
artifacts: multiPlatformArtifacts(
'NimbleBrainInc/mcp-server-nationalparks',
'0.1.2',
83_000,
),
},
{
version: '0.1.3',
Expand All @@ -616,7 +625,11 @@ const PACKAGES: SeedPackage[] = [
releaseUrl:
'https://github.com/NimbleBrainInc/mcp-server-nationalparks/releases/tag/v0.1.3',
manifest: nationalparksManifest('0.1.3'),
artifacts: multiPlatformArtifacts('NimbleBrainInc/mcp-server-nationalparks', '0.1.3', 83_500),
artifacts: multiPlatformArtifacts(
'NimbleBrainInc/mcp-server-nationalparks',
'0.1.3',
83_500,
),
},
{
version: '0.1.4',
Expand All @@ -629,7 +642,11 @@ const PACKAGES: SeedPackage[] = [
releaseUrl:
'https://github.com/NimbleBrainInc/mcp-server-nationalparks/releases/tag/v0.1.4',
manifest: nationalparksManifest('0.1.4'),
artifacts: multiPlatformArtifacts('NimbleBrainInc/mcp-server-nationalparks', '0.1.4', 84_000),
artifacts: multiPlatformArtifacts(
'NimbleBrainInc/mcp-server-nationalparks',
'0.1.4',
84_000,
),
},
{
version: '0.1.5',
Expand All @@ -642,7 +659,11 @@ const PACKAGES: SeedPackage[] = [
releaseUrl:
'https://github.com/NimbleBrainInc/mcp-server-nationalparks/releases/tag/v0.1.5',
manifest: nationalparksManifest('0.1.5'),
artifacts: multiPlatformArtifacts('NimbleBrainInc/mcp-server-nationalparks', '0.1.5', 84_500),
artifacts: multiPlatformArtifacts(
'NimbleBrainInc/mcp-server-nationalparks',
'0.1.5',
84_500,
),
},
{
version: '0.2.0',
Expand All @@ -655,7 +676,11 @@ const PACKAGES: SeedPackage[] = [
releaseUrl:
'https://github.com/NimbleBrainInc/mcp-server-nationalparks/releases/tag/v0.2.0',
manifest: nationalparksManifest('0.2.0'),
artifacts: multiPlatformArtifacts('NimbleBrainInc/mcp-server-nationalparks', '0.2.0', 86_000),
artifacts: multiPlatformArtifacts(
'NimbleBrainInc/mcp-server-nationalparks',
'0.2.0',
86_000,
),
},
],
},
Expand All @@ -667,26 +692,43 @@ const PACKAGES: SeedPackage[] = [

/** Generate a deterministic fake digest from a string */
function fakeDigest(input: string): string {
return 'sha256:' + createHash('sha256').update(input).digest('hex');
return `sha256:${createHash('sha256').update(input).digest('hex')}`;
}

/** Universal artifact for python/any-platform bundles */
function universalArtifact(repo: string, version: string, sizeBytes: number): SeedArtifact[] {
return [{
os: 'any',
arch: 'any',
sizeBytes,
sourceUrl: `https://github.com/${repo}/releases/download/v${version}/${repo.split('/')[1]}-${version}.mcpb`,
}];
return [
{
os: 'any',
arch: 'any',
sizeBytes,
sourceUrl: `https://github.com/${repo}/releases/download/v${version}/${repo.split('/')[1]}-${version}.mcpb`,
},
];
}

/** Multi-platform artifacts for node bundles */
function multiPlatformArtifacts(repo: string, version: string, sizeBytes: number): SeedArtifact[] {
const name = repo.split('/')[1];
return [
{ os: 'darwin', arch: 'arm64', sizeBytes, sourceUrl: `https://github.com/${repo}/releases/download/v${version}/${name}-${version}-darwin-arm64.mcpb` },
{ os: 'darwin', arch: 'x64', sizeBytes: sizeBytes + 1024, sourceUrl: `https://github.com/${repo}/releases/download/v${version}/${name}-${version}-darwin-x64.mcpb` },
{ os: 'linux', arch: 'x64', sizeBytes: sizeBytes + 2048, sourceUrl: `https://github.com/${repo}/releases/download/v${version}/${name}-${version}-linux-x64.mcpb` },
{
os: 'darwin',
arch: 'arm64',
sizeBytes,
sourceUrl: `https://github.com/${repo}/releases/download/v${version}/${name}-${version}-darwin-arm64.mcpb`,
},
{
os: 'darwin',
arch: 'x64',
sizeBytes: sizeBytes + 1024,
sourceUrl: `https://github.com/${repo}/releases/download/v${version}/${name}-${version}-darwin-x64.mcpb`,
},
{
os: 'linux',
arch: 'x64',
sizeBytes: sizeBytes + 2048,
sourceUrl: `https://github.com/${repo}/releases/download/v${version}/${name}-${version}-linux-x64.mcpb`,
},
];
}

Expand Down Expand Up @@ -865,7 +907,7 @@ async function seed() {
});

// Create placeholder file on disk so local storage can serve it
const storagePath = process.env['STORAGE_PATH'] || './packages';
const storagePath = process.env.STORAGE_PATH || './packages';
const fullPath = join(storagePath, artifactPath);
await mkdir(dirname(fullPath), { recursive: true });
await writeFile(fullPath, `placeholder:${p.name}@${v.version}:${a.os}-${a.arch}`);
Expand Down
65 changes: 35 additions & 30 deletions apps/registry/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,51 +4,56 @@ dotenvConfig({ quiet: true });

export const config = {
server: {
port: parseInt(process.env['PORT'] || '3200', 10),
host: process.env['HOST'] || '0.0.0.0',
nodeEnv: process.env['NODE_ENV'] || 'development',
port: parseInt(process.env.PORT || '3200', 10),
host: process.env.HOST || '0.0.0.0',
nodeEnv: process.env.NODE_ENV || 'development',
// Allowed origins for CORS (comma-separated in env)
corsOrigins: process.env['CORS_ORIGINS']?.split(',').map(s => s.trim()).filter(Boolean) || [],
corsOrigins:
process.env.CORS_ORIGINS?.split(',')
.map((s) => s.trim())
.filter(Boolean) || [],
},
clerk: {
publishableKey: process.env['CLERK_PUBLISHABLE_KEY'] || '',
secretKey: process.env['CLERK_SECRET_KEY'] || '',
publishableKey: process.env.CLERK_PUBLISHABLE_KEY || '',
secretKey: process.env.CLERK_SECRET_KEY || '',
},
database: {
url: process.env['DATABASE_URL'] || 'postgresql://localhost:5432/mcpb_registry',
url: process.env.DATABASE_URL || 'postgresql://localhost:5432/mcpb_registry',
},
storage: {
type: (process.env['STORAGE_TYPE'] || 'local') as 'local' | 's3',
path: process.env['STORAGE_PATH'] || './packages',
type: (process.env.STORAGE_TYPE || 'local') as 'local' | 's3',
path: process.env.STORAGE_PATH || './packages',
s3: {
bucket: process.env['S3_BUCKET'] || '',
region: process.env['S3_REGION'] || 'us-east-1',
accessKeyId: process.env['S3_ACCESS_KEY_ID'] || '',
secretAccessKey: process.env['S3_SECRET_ACCESS_KEY'] || '',
bucket: process.env.S3_BUCKET || '',
region: process.env.S3_REGION || 'us-east-1',
accessKeyId: process.env.S3_ACCESS_KEY_ID || '',
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY || '',
},
cloudfront: {
domain: process.env['CLOUDFRONT_DOMAIN'] || '',
keyPairId: process.env['CLOUDFRONT_KEY_PAIR_ID'] || '',
privateKeyPath: process.env['CLOUDFRONT_PRIVATE_KEY_PATH'] || '',
privateKey: process.env['CLOUDFRONT_PRIVATE_KEY'] || '',
privateKeyBase64: process.env['CLOUDFRONT_PRIVATE_KEY_BASE64'] || '',
urlExpirationSeconds: parseInt(process.env['CLOUDFRONT_URL_EXPIRATION'] || '900', 10),
domain: process.env.CLOUDFRONT_DOMAIN || '',
keyPairId: process.env.CLOUDFRONT_KEY_PAIR_ID || '',
privateKeyPath: process.env.CLOUDFRONT_PRIVATE_KEY_PATH || '',
privateKey: process.env.CLOUDFRONT_PRIVATE_KEY || '',
privateKeyBase64: process.env.CLOUDFRONT_PRIVATE_KEY_BASE64 || '',
urlExpirationSeconds: parseInt(process.env.CLOUDFRONT_URL_EXPIRATION || '900', 10),
},
},
limits: {
maxBundleSizeMB: parseInt(process.env['MAX_BUNDLE_SIZE_MB'] || '50', 10),
maxBundleSizeMB: parseInt(process.env.MAX_BUNDLE_SIZE_MB || '50', 10),
},
scanner: {
enabled: process.env['SCANNER_ENABLED'] === 'true',
image: process.env['SCANNER_IMAGE'] || '',
imageTag: process.env['SCANNER_IMAGE_TAG'] || 'latest',
namespace: process.env['SCANNER_NAMESPACE'] || 'security-scanning',
callbackSecret: process.env['SCANNER_CALLBACK_SECRET'] || '',
callbackUrl: process.env['SCANNER_CALLBACK_URL'] || `http://localhost:${process.env['PORT'] || '3200'}/app/scan-results`,
secretName: process.env['SCANNER_SECRET_NAME'] || 'scanner-secrets',
s3ResultPrefix: process.env['SCANNER_S3_RESULT_PREFIX'] || 'scan-results/',
ttlSeconds: parseInt(process.env['SCANNER_TTL_SECONDS'] || '3600', 10),
activeDeadlineSeconds: parseInt(process.env['SCANNER_ACTIVE_DEADLINE'] || '900', 10),
enabled: process.env.SCANNER_ENABLED === 'true',
image: process.env.SCANNER_IMAGE || '',
imageTag: process.env.SCANNER_IMAGE_TAG || 'latest',
namespace: process.env.SCANNER_NAMESPACE || 'security-scanning',
callbackSecret: process.env.SCANNER_CALLBACK_SECRET || '',
callbackUrl:
process.env.SCANNER_CALLBACK_URL ||
`http://localhost:${process.env.PORT || '3200'}/app/scan-results`,
secretName: process.env.SCANNER_SECRET_NAME || 'scanner-secrets',
s3ResultPrefix: process.env.SCANNER_S3_RESULT_PREFIX || 'scan-results/',
ttlSeconds: parseInt(process.env.SCANNER_TTL_SECONDS || '3600', 10),
activeDeadlineSeconds: parseInt(process.env.SCANNER_ACTIVE_DEADLINE || '900', 10),
},
};

Expand Down
Loading
Loading