@hasna/mcps 0.0.13 → 0.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/index.js +371 -3
- package/bin/mcp.js +271 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +376 -6
- package/dist/lib/provider-profile-seeds.d.ts +2 -0
- package/dist/lib/provider-profiles.d.ts +14 -0
- package/dist/mcp/index.js +271 -0
- package/dist/types.d.ts +82 -2
- package/package.json +2 -2
package/bin/mcp.js
CHANGED
|
@@ -16577,6 +16577,85 @@ var init_config2 = __esm(() => {
|
|
|
16577
16577
|
DB_PATH = process.env.HASNA_MCPS_DB_PATH ?? process.env.MCPS_DB_PATH ?? join7(MCPS_DIR, "registry.db");
|
|
16578
16578
|
});
|
|
16579
16579
|
|
|
16580
|
+
// src/lib/provider-profile-seeds.ts
|
|
16581
|
+
var DEFAULT_PROVIDER_PROFILE_SEEDS;
|
|
16582
|
+
var init_provider_profile_seeds = __esm(() => {
|
|
16583
|
+
DEFAULT_PROVIDER_PROFILE_SEEDS = [
|
|
16584
|
+
{
|
|
16585
|
+
id: "notion",
|
|
16586
|
+
displayName: "Notion",
|
|
16587
|
+
description: "Connect a Notion workspace so agents can search, read, create, and update workspace content.",
|
|
16588
|
+
endpoint: "https://mcp.notion.com/mcp",
|
|
16589
|
+
transport: "streamable-http",
|
|
16590
|
+
fallbackEndpoints: [
|
|
16591
|
+
{
|
|
16592
|
+
transport: "sse",
|
|
16593
|
+
url: "https://mcp.notion.com/sse",
|
|
16594
|
+
notes: "Fallback for clients that do not support Streamable HTTP."
|
|
16595
|
+
}
|
|
16596
|
+
],
|
|
16597
|
+
authType: "oauth2",
|
|
16598
|
+
authMetadata: {
|
|
16599
|
+
oauthVersion: "2.0",
|
|
16600
|
+
pkce: true,
|
|
16601
|
+
dynamicClientRegistration: true,
|
|
16602
|
+
bearerToken: "none",
|
|
16603
|
+
notes: "Remote Notion MCP uses OAuth with PKCE. Bearer-token authentication is only appropriate for self-hosted/local fallback deployments."
|
|
16604
|
+
},
|
|
16605
|
+
tokenMode: "workspace",
|
|
16606
|
+
installFallback: {
|
|
16607
|
+
command: "npx",
|
|
16608
|
+
args: ["-y", "mcp-remote", "https://mcp.notion.com/sse", "--transport", "sse-only"],
|
|
16609
|
+
packageName: "mcp-remote",
|
|
16610
|
+
url: "https://mcp.notion.com/sse"
|
|
16611
|
+
},
|
|
16612
|
+
docsUrl: "https://developers.notion.com/guides/mcp/build-mcp-client",
|
|
16613
|
+
safety: {
|
|
16614
|
+
requiresApproval: true,
|
|
16615
|
+
dataClasses: ["workspace_content", "pages", "databases", "comments"],
|
|
16616
|
+
notes: "Connected agents operate with the authorizing user's workspace access. Human confirmation is recommended for write-capable workflows."
|
|
16617
|
+
},
|
|
16618
|
+
provenance: {
|
|
16619
|
+
source: "curated",
|
|
16620
|
+
sourceUrl: "https://developers.notion.com/guides/mcp/build-mcp-client",
|
|
16621
|
+
verifiedAt: "2026-05-10"
|
|
16622
|
+
}
|
|
16623
|
+
},
|
|
16624
|
+
{
|
|
16625
|
+
id: "linear",
|
|
16626
|
+
displayName: "Linear",
|
|
16627
|
+
description: "Connect Linear so agents can find, create, and update issues, projects, comments, and related workspace objects.",
|
|
16628
|
+
endpoint: "https://mcp.linear.app/mcp",
|
|
16629
|
+
transport: "streamable-http",
|
|
16630
|
+
authType: "oauth2",
|
|
16631
|
+
authMetadata: {
|
|
16632
|
+
oauthVersion: "2.1",
|
|
16633
|
+
dynamicClientRegistration: true,
|
|
16634
|
+
bearerToken: "optional",
|
|
16635
|
+
notes: "Linear supports interactive OAuth 2.1 with dynamic client registration and optional Authorization: Bearer tokens for OAuth tokens or API keys."
|
|
16636
|
+
},
|
|
16637
|
+
tokenMode: "workspace",
|
|
16638
|
+
installFallback: {
|
|
16639
|
+
command: "npx",
|
|
16640
|
+
args: ["-y", "mcp-remote", "https://mcp.linear.app/mcp"],
|
|
16641
|
+
packageName: "mcp-remote",
|
|
16642
|
+
url: "https://mcp.linear.app/mcp"
|
|
16643
|
+
},
|
|
16644
|
+
docsUrl: "https://linear.app/docs/mcp",
|
|
16645
|
+
safety: {
|
|
16646
|
+
requiresApproval: true,
|
|
16647
|
+
dataClasses: ["issues", "projects", "comments", "teams", "users"],
|
|
16648
|
+
notes: "Linear tools can create and update workspace objects, so write actions should be policy-gated by the platform."
|
|
16649
|
+
},
|
|
16650
|
+
provenance: {
|
|
16651
|
+
source: "curated",
|
|
16652
|
+
sourceUrl: "https://linear.app/docs/mcp",
|
|
16653
|
+
verifiedAt: "2026-05-10"
|
|
16654
|
+
}
|
|
16655
|
+
}
|
|
16656
|
+
];
|
|
16657
|
+
});
|
|
16658
|
+
|
|
16580
16659
|
// src/lib/db.ts
|
|
16581
16660
|
import { mkdirSync as mkdirSync5 } from "fs";
|
|
16582
16661
|
function getDb() {
|
|
@@ -16662,6 +16741,50 @@ function getDb() {
|
|
|
16662
16741
|
('github-mcp-topic', 'GitHub MCP Topic', 'github-topic', 'https://api.github.com/search/repositories', 'GitHub repositories tagged with mcp-server topic')
|
|
16663
16742
|
`);
|
|
16664
16743
|
}
|
|
16744
|
+
db.exec(`
|
|
16745
|
+
CREATE TABLE IF NOT EXISTS provider_profiles (
|
|
16746
|
+
id TEXT PRIMARY KEY,
|
|
16747
|
+
display_name TEXT NOT NULL,
|
|
16748
|
+
description TEXT,
|
|
16749
|
+
endpoint TEXT,
|
|
16750
|
+
transport TEXT NOT NULL,
|
|
16751
|
+
fallback_endpoints TEXT NOT NULL DEFAULT '[]',
|
|
16752
|
+
auth_type TEXT NOT NULL,
|
|
16753
|
+
auth_metadata TEXT NOT NULL DEFAULT '{}',
|
|
16754
|
+
scopes TEXT NOT NULL DEFAULT '[]',
|
|
16755
|
+
token_mode TEXT NOT NULL DEFAULT 'none',
|
|
16756
|
+
install_fallback TEXT NOT NULL DEFAULT '{}',
|
|
16757
|
+
docs_url TEXT,
|
|
16758
|
+
safety TEXT NOT NULL DEFAULT '{}',
|
|
16759
|
+
provenance TEXT NOT NULL DEFAULT '{"source":"manual"}',
|
|
16760
|
+
enabled INTEGER NOT NULL DEFAULT 1,
|
|
16761
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
16762
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
16763
|
+
)
|
|
16764
|
+
`);
|
|
16765
|
+
try {
|
|
16766
|
+
db.exec("ALTER TABLE provider_profiles ADD COLUMN fallback_endpoints TEXT NOT NULL DEFAULT '[]'");
|
|
16767
|
+
} catch {}
|
|
16768
|
+
try {
|
|
16769
|
+
db.exec("ALTER TABLE provider_profiles ADD COLUMN auth_metadata TEXT NOT NULL DEFAULT '{}'");
|
|
16770
|
+
} catch {}
|
|
16771
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_provider_profiles_enabled ON provider_profiles(enabled)");
|
|
16772
|
+
const providerProfileCount = db.query("SELECT COUNT(*) as c FROM provider_profiles").get().c;
|
|
16773
|
+
if (providerProfileCount === 0) {
|
|
16774
|
+
const insertProviderProfile = db.prepare(`
|
|
16775
|
+
INSERT OR IGNORE INTO provider_profiles (
|
|
16776
|
+
id, display_name, description, endpoint, transport, fallback_endpoints,
|
|
16777
|
+
auth_type, auth_metadata, scopes, token_mode, install_fallback,
|
|
16778
|
+
docs_url, safety, provenance, enabled
|
|
16779
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
16780
|
+
`);
|
|
16781
|
+
const run = db.transaction(() => {
|
|
16782
|
+
for (const profile of DEFAULT_PROVIDER_PROFILE_SEEDS) {
|
|
16783
|
+
insertProviderProfile.run(profile.id, profile.displayName, profile.description ?? null, profile.endpoint ?? null, profile.transport, JSON.stringify(profile.fallbackEndpoints ?? []), profile.authType, JSON.stringify(profile.authMetadata ?? {}), JSON.stringify(profile.scopes ?? []), profile.tokenMode ?? "none", JSON.stringify(profile.installFallback ?? null), profile.docsUrl ?? null, JSON.stringify(profile.safety ?? {}), JSON.stringify(profile.provenance), profile.enabled === false ? 0 : 1);
|
|
16784
|
+
}
|
|
16785
|
+
});
|
|
16786
|
+
run();
|
|
16787
|
+
}
|
|
16665
16788
|
db.exec(`
|
|
16666
16789
|
CREATE TABLE IF NOT EXISTS feedback (
|
|
16667
16790
|
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
|
|
@@ -16685,6 +16808,7 @@ var db = null, _adapter = null;
|
|
|
16685
16808
|
var init_db = __esm(() => {
|
|
16686
16809
|
init_dist();
|
|
16687
16810
|
init_config2();
|
|
16811
|
+
init_provider_profile_seeds();
|
|
16688
16812
|
});
|
|
16689
16813
|
|
|
16690
16814
|
// src/lib/sources.ts
|
|
@@ -34395,6 +34519,104 @@ async function runFleetInstall(options = {}, dependencies = {}) {
|
|
|
34395
34519
|
}));
|
|
34396
34520
|
}
|
|
34397
34521
|
|
|
34522
|
+
// src/lib/provider-profiles.ts
|
|
34523
|
+
init_db();
|
|
34524
|
+
init_provider_profile_seeds();
|
|
34525
|
+
var TRANSPORTS = new Set(["stdio", "sse", "streamable-http"]);
|
|
34526
|
+
var AUTH_TYPES = new Set(["none", "oauth2", "api_key", "bearer_token", "custom"]);
|
|
34527
|
+
var TOKEN_MODES = new Set(["none", "user", "workspace", "service"]);
|
|
34528
|
+
var BEARER_TOKEN_MODES = new Set(["none", "optional", "required"]);
|
|
34529
|
+
var PROVENANCE_SOURCES = new Set(["curated", "official-registry", "npm", "github", "manual"]);
|
|
34530
|
+
function safeJsonParse2(value, fallback) {
|
|
34531
|
+
if (typeof value !== "string")
|
|
34532
|
+
return fallback;
|
|
34533
|
+
try {
|
|
34534
|
+
return JSON.parse(value);
|
|
34535
|
+
} catch {
|
|
34536
|
+
return fallback;
|
|
34537
|
+
}
|
|
34538
|
+
}
|
|
34539
|
+
function normalizeId(id) {
|
|
34540
|
+
const normalized = id.trim().toLowerCase();
|
|
34541
|
+
if (!/^[a-z0-9][a-z0-9-]*[a-z0-9]$|^[a-z0-9]$/.test(normalized)) {
|
|
34542
|
+
throw new Error("Provider profile id must be lowercase kebab-case");
|
|
34543
|
+
}
|
|
34544
|
+
return normalized;
|
|
34545
|
+
}
|
|
34546
|
+
function parseRow3(row) {
|
|
34547
|
+
const installFallback = safeJsonParse2(row.install_fallback, null);
|
|
34548
|
+
return {
|
|
34549
|
+
id: row.id,
|
|
34550
|
+
displayName: row.display_name,
|
|
34551
|
+
description: row.description || null,
|
|
34552
|
+
endpoint: row.endpoint || null,
|
|
34553
|
+
transport: row.transport,
|
|
34554
|
+
fallbackEndpoints: safeJsonParse2(row.fallback_endpoints, []),
|
|
34555
|
+
authType: row.auth_type,
|
|
34556
|
+
authMetadata: safeJsonParse2(row.auth_metadata, {}),
|
|
34557
|
+
scopes: safeJsonParse2(row.scopes, []),
|
|
34558
|
+
tokenMode: row.token_mode,
|
|
34559
|
+
installFallback,
|
|
34560
|
+
docsUrl: row.docs_url || null,
|
|
34561
|
+
safety: safeJsonParse2(row.safety, {}),
|
|
34562
|
+
provenance: safeJsonParse2(row.provenance, { source: "manual" }),
|
|
34563
|
+
enabled: row.enabled === 1 || row.enabled === true,
|
|
34564
|
+
created_at: row.created_at,
|
|
34565
|
+
updated_at: row.updated_at
|
|
34566
|
+
};
|
|
34567
|
+
}
|
|
34568
|
+
function listProviderProfiles(options = {}) {
|
|
34569
|
+
const db2 = getDb();
|
|
34570
|
+
const sql = options.enabledOnly ? "SELECT * FROM provider_profiles WHERE enabled = 1 ORDER BY display_name" : "SELECT * FROM provider_profiles ORDER BY display_name";
|
|
34571
|
+
return db2.prepare(sql).all().map(parseRow3);
|
|
34572
|
+
}
|
|
34573
|
+
function searchProviderProfiles(query, options = {}) {
|
|
34574
|
+
const normalizedQuery = query.trim().toLowerCase();
|
|
34575
|
+
if (!normalizedQuery)
|
|
34576
|
+
return listProviderProfiles(options);
|
|
34577
|
+
return listProviderProfiles(options).filter((profile) => {
|
|
34578
|
+
const searchable = [
|
|
34579
|
+
profile.id,
|
|
34580
|
+
profile.displayName,
|
|
34581
|
+
profile.description ?? "",
|
|
34582
|
+
profile.endpoint ?? "",
|
|
34583
|
+
profile.docsUrl ?? "",
|
|
34584
|
+
profile.provenance.sourceUrl ?? "",
|
|
34585
|
+
profile.provenance.packageName ?? ""
|
|
34586
|
+
].join(`
|
|
34587
|
+
`).toLowerCase();
|
|
34588
|
+
return searchable.includes(normalizedQuery);
|
|
34589
|
+
});
|
|
34590
|
+
}
|
|
34591
|
+
function getProviderProfile(id) {
|
|
34592
|
+
const db2 = getDb();
|
|
34593
|
+
const row = db2.prepare("SELECT * FROM provider_profiles WHERE id = ?").get(normalizeId(id));
|
|
34594
|
+
return row ? parseRow3(row) : null;
|
|
34595
|
+
}
|
|
34596
|
+
function installProviderProfile(id, options = {}) {
|
|
34597
|
+
const profile = getProviderProfile(id);
|
|
34598
|
+
if (!profile)
|
|
34599
|
+
throw new Error(`Provider profile "${id}" not found`);
|
|
34600
|
+
if (!profile.enabled)
|
|
34601
|
+
throw new Error(`Provider profile "${id}" is disabled`);
|
|
34602
|
+
const fallback = profile.installFallback;
|
|
34603
|
+
const useFallback = options.useFallback || !profile.endpoint;
|
|
34604
|
+
const command = useFallback ? fallback?.command : fallback?.command ?? "npx";
|
|
34605
|
+
const args = useFallback ? fallback?.args ?? [] : fallback?.args ?? [];
|
|
34606
|
+
if (!command) {
|
|
34607
|
+
throw new Error(`Provider profile "${id}" does not define an install fallback command`);
|
|
34608
|
+
}
|
|
34609
|
+
return addServer({
|
|
34610
|
+
name: options.name ?? profile.displayName,
|
|
34611
|
+
description: profile.description ?? undefined,
|
|
34612
|
+
command,
|
|
34613
|
+
args,
|
|
34614
|
+
transport: useFallback ? "stdio" : profile.transport,
|
|
34615
|
+
url: useFallback ? fallback?.url : profile.endpoint ?? undefined,
|
|
34616
|
+
source: "provider-profile"
|
|
34617
|
+
});
|
|
34618
|
+
}
|
|
34619
|
+
|
|
34398
34620
|
// src/mcp/tools.ts
|
|
34399
34621
|
var VERSION = readPackageVersion(import.meta.url);
|
|
34400
34622
|
var mcpsAgents = new Map;
|
|
@@ -34561,6 +34783,55 @@ function buildMcpTools() {
|
|
|
34561
34783
|
limit: typeof limit === "number" ? limit : undefined
|
|
34562
34784
|
}))
|
|
34563
34785
|
},
|
|
34786
|
+
{
|
|
34787
|
+
name: "list_provider_profiles",
|
|
34788
|
+
description: "List curated provider profiles for hosted/common MCP integrations such as Notion and Linear.",
|
|
34789
|
+
paramsSchema: {
|
|
34790
|
+
enabled_only: exports_external2.boolean().optional().describe("Only include enabled provider profiles")
|
|
34791
|
+
},
|
|
34792
|
+
run: ({ enabled_only }) => jsonContent(listProviderProfiles({ enabledOnly: enabled_only === true }))
|
|
34793
|
+
},
|
|
34794
|
+
{
|
|
34795
|
+
name: "search_provider_profiles",
|
|
34796
|
+
description: "Search curated provider profiles separately from raw MCP registry/source search.",
|
|
34797
|
+
paramsSchema: {
|
|
34798
|
+
query: exports_external2.string().describe("Search query such as 'notion', 'linear', or an endpoint URL"),
|
|
34799
|
+
enabled_only: exports_external2.boolean().optional().describe("Only include enabled provider profiles")
|
|
34800
|
+
},
|
|
34801
|
+
run: ({ query, enabled_only }) => jsonContent(searchProviderProfiles(String(query), { enabledOnly: enabled_only === true }))
|
|
34802
|
+
},
|
|
34803
|
+
{
|
|
34804
|
+
name: "get_provider_profile",
|
|
34805
|
+
description: "Get one curated provider profile by ID.",
|
|
34806
|
+
paramsSchema: {
|
|
34807
|
+
id: exports_external2.string().describe("Provider profile ID")
|
|
34808
|
+
},
|
|
34809
|
+
run: ({ id }) => {
|
|
34810
|
+
const profile = getProviderProfile(String(id));
|
|
34811
|
+
if (!profile)
|
|
34812
|
+
return errorContent(`Provider profile "${String(id)}" not found.`);
|
|
34813
|
+
return jsonContent(profile);
|
|
34814
|
+
}
|
|
34815
|
+
},
|
|
34816
|
+
{
|
|
34817
|
+
name: "install_provider_profile",
|
|
34818
|
+
description: "Register a curated provider profile as an MCP server.",
|
|
34819
|
+
paramsSchema: {
|
|
34820
|
+
id: exports_external2.string().describe("Provider profile ID"),
|
|
34821
|
+
name: exports_external2.string().optional().describe("Override registered server name"),
|
|
34822
|
+
use_fallback: exports_external2.boolean().optional().describe("Install the stdio fallback command instead of the direct remote transport")
|
|
34823
|
+
},
|
|
34824
|
+
run: ({ id, name, use_fallback }) => {
|
|
34825
|
+
try {
|
|
34826
|
+
return jsonContent(redactServerEnv(installProviderProfile(String(id), {
|
|
34827
|
+
name: typeof name === "string" ? name : undefined,
|
|
34828
|
+
useFallback: use_fallback === true
|
|
34829
|
+
})));
|
|
34830
|
+
} catch (err) {
|
|
34831
|
+
return errorContent(err.message);
|
|
34832
|
+
}
|
|
34833
|
+
}
|
|
34834
|
+
},
|
|
34564
34835
|
{
|
|
34565
34836
|
name: "list_sources",
|
|
34566
34837
|
description: "List all configured search sources for finding MCP servers",
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { McpServerEntry, AddServerOptions, McpTool, RegistryServer, ConnectedServer, FinderResult, MachineEntry, AddMachineOptions, MachinePlatform, MachineArch, MachineInstaller, HasnaMcpCatalogEntry, MachinePackageHealth, FleetHealthReport, FleetInstallPackageResult, FleetInstallReport, } from "./types.js";
|
|
1
|
+
export type { McpServerEntry, AddServerOptions, McpTool, RegistryServer, ConnectedServer, FinderResult, MachineEntry, AddMachineOptions, MachinePlatform, MachineArch, MachineInstaller, HasnaMcpCatalogEntry, MachinePackageHealth, FleetHealthReport, FleetInstallPackageResult, FleetInstallReport, ProviderAuthMetadata, ProviderEndpointFallback, ProviderInstallFallback, ProviderProfile, ProviderProfileAuthType, ProviderProfileBearerTokenMode, ProviderProfileSource, ProviderProfileTokenMode, ProviderProfileTransport, ProviderSafetyMetadata, ProviderSourceProvenance, InstallProviderProfileOptions, UpsertProviderProfileOptions, } from "./types.js";
|
|
2
2
|
export { addServer, removeServer, listServers, getServer, updateServer, enableServer, disableServer, getToolCounts, getCachedTools, setServerEnv, unsetServerEnv, cloneServer, } from "./lib/registry.js";
|
|
3
3
|
export { diagnoseServer } from "./lib/doctor.js";
|
|
4
4
|
export type { DoctorReport, DoctorCheck } from "./lib/doctor.js";
|
|
@@ -6,6 +6,8 @@ export { searchRegistry, getRegistryServer, installFromRegistry } from "./lib/re
|
|
|
6
6
|
export { findServers, listAwesomeServers } from "./lib/finder.js";
|
|
7
7
|
export type { FindOptions } from "./lib/finder.js";
|
|
8
8
|
export { listSources, getSource, addSource, removeSource, enableSource, disableSource, } from "./lib/sources.js";
|
|
9
|
+
export { upsertProviderProfile, listProviderProfiles, searchProviderProfiles, getProviderProfile, installProviderProfile, removeProviderProfile, enableProviderProfile, disableProviderProfile, seedDefaultProviderProfiles, } from "./lib/provider-profiles.js";
|
|
10
|
+
export { DEFAULT_PROVIDER_PROFILE_SEEDS } from "./lib/provider-profile-seeds.js";
|
|
9
11
|
export { installToAgents } from "./lib/install.js";
|
|
10
12
|
export type { AgentTarget, InstallResult } from "./lib/install.js";
|
|
11
13
|
export type { McpSource, AddSourceOptions } from "./types.js";
|