@oisincoveney/pipeline 1.8.0 → 1.8.1
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/README.md +11 -5
- package/defaults/install-manifest.json +2 -4
- package/dist/pipeline-init.js +54 -18
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -37,11 +37,17 @@ Momokaya remote endpoint
|
|
|
37
37
|
|
|
38
38
|
The default GitHub MCP registration uses GitHub's official container in
|
|
39
39
|
read-only mode and reads `GITHUB_PERSONAL_ACCESS_TOKEN` from the environment.
|
|
40
|
-
The Momokaya Qdrant endpoint is protected by Traefik HTTP Basic auth. Set
|
|
41
|
-
`
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
The Momokaya Qdrant endpoint is protected by Traefik HTTP Basic auth. Set
|
|
41
|
+
`MEMORY_MCP_BASIC_AUTH` to the base64 `user:password` payload before running
|
|
42
|
+
`pipe init` if you want init to register that remote server with MCPM:
|
|
43
|
+
|
|
44
|
+
```shell
|
|
45
|
+
export MEMORY_MCP_BASIC_AUTH="$(printf '%s' 'user:password' | base64)"
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
When `MEMORY_MCP_BASIC_AUTH` is not set, `pipe init` still writes the default
|
|
49
|
+
scaffold and keeps the generated `qdrant` MCP entry, but skips immediate MCPM
|
|
50
|
+
registration for that private endpoint.
|
|
45
51
|
|
|
46
52
|
Check local prerequisites and config health:
|
|
47
53
|
|
|
@@ -78,12 +78,10 @@
|
|
|
78
78
|
"name": "oisin-pipeline-qdrant",
|
|
79
79
|
"transport": "remote",
|
|
80
80
|
"url": "https://memory-mcp.momokaya.ee/mcp/",
|
|
81
|
+
"optionalRegistration": true,
|
|
81
82
|
"headers": {
|
|
82
83
|
"Authorization": {
|
|
83
|
-
"sources": [
|
|
84
|
-
{ "env": "MOMOKAYA_MCP_AUTHORIZATION" },
|
|
85
|
-
{ "env": "MEMORY_MCP_BASIC_AUTH", "prefix": "Basic " }
|
|
86
|
-
]
|
|
84
|
+
"sources": [{ "env": "MEMORY_MCP_BASIC_AUTH", "prefix": "Basic " }]
|
|
87
85
|
}
|
|
88
86
|
}
|
|
89
87
|
},
|
package/dist/pipeline-init.js
CHANGED
|
@@ -29,6 +29,18 @@ var PipelineMcpInstallError = class extends Error {
|
|
|
29
29
|
this.name = "PipelineMcpInstallError";
|
|
30
30
|
}
|
|
31
31
|
};
|
|
32
|
+
var PipelineMcpMissingCredentialError = class extends PipelineMcpInstallError {
|
|
33
|
+
headerName;
|
|
34
|
+
missingEnv;
|
|
35
|
+
serverName;
|
|
36
|
+
constructor(serverName, headerName, missingEnv) {
|
|
37
|
+
super([`MCP server ${serverName} requires ${headerName} credentials before it can be registered.`, `Set ${missingEnv.join(" or ")} and re-run pipeline init.`].join("\n"));
|
|
38
|
+
this.name = "PipelineMcpMissingCredentialError";
|
|
39
|
+
this.serverName = serverName;
|
|
40
|
+
this.headerName = headerName;
|
|
41
|
+
this.missingEnv = missingEnv;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
32
44
|
var PipelineDefaultManifestError = class extends Error {
|
|
33
45
|
constructor(message) {
|
|
34
46
|
super(message);
|
|
@@ -58,6 +70,7 @@ const pipelineMcpInstallSpecSchema = z.object({
|
|
|
58
70
|
env: z.record(z.string(), z.string()).optional(),
|
|
59
71
|
headers: z.record(z.string(), pipelineMcpHeaderValueSchema).optional(),
|
|
60
72
|
name: z.string().min(1),
|
|
73
|
+
optionalRegistration: z.boolean().optional(),
|
|
61
74
|
transport: z.enum(["remote", "stdio"]),
|
|
62
75
|
url: z.string().url().optional()
|
|
63
76
|
}).strict().superRefine((spec, ctx) => {
|
|
@@ -824,8 +837,13 @@ async function installDefaultSkillsWithCli(specs, cwd) {
|
|
|
824
837
|
}
|
|
825
838
|
}
|
|
826
839
|
async function installDefaultMcpsWithCli(specs, cwd) {
|
|
840
|
+
const skipped = [];
|
|
827
841
|
for (const spec of specs) {
|
|
828
842
|
const install = mcpInstallArgs(spec);
|
|
843
|
+
if ("skipped" in install) {
|
|
844
|
+
skipped.push(install.skipped);
|
|
845
|
+
continue;
|
|
846
|
+
}
|
|
829
847
|
try {
|
|
830
848
|
await execa("uvx", [...DEFAULT_MCPM_ARGS, ...install.args], {
|
|
831
849
|
cwd,
|
|
@@ -848,6 +866,7 @@ async function installDefaultMcpsWithCli(specs, cwd) {
|
|
|
848
866
|
].filter(Boolean).join("\n"));
|
|
849
867
|
}
|
|
850
868
|
}
|
|
869
|
+
return { skipped };
|
|
851
870
|
}
|
|
852
871
|
function mcpInstallArgs(spec) {
|
|
853
872
|
if (spec.catalog) return {
|
|
@@ -870,19 +889,29 @@ function mcpInstallArgs(spec) {
|
|
|
870
889
|
if (spec.transport === "remote") {
|
|
871
890
|
if (!spec.url) throw new PipelineMcpInstallError(`MCP server ${spec.name} is remote but has no url.`);
|
|
872
891
|
const redactions = [];
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
892
|
+
try {
|
|
893
|
+
const headers = Object.entries(spec.headers ?? {}).flatMap(([key, value]) => {
|
|
894
|
+
const headerValue = resolveMcpHeaderValue(spec.name, key, value);
|
|
895
|
+
redactions.push(headerValue);
|
|
896
|
+
return ["--headers", `${key}=${headerValue}`];
|
|
897
|
+
});
|
|
898
|
+
return {
|
|
899
|
+
args: [
|
|
900
|
+
...args,
|
|
901
|
+
"--url",
|
|
902
|
+
spec.url,
|
|
903
|
+
...headers
|
|
904
|
+
],
|
|
905
|
+
redactions
|
|
906
|
+
};
|
|
907
|
+
} catch (err) {
|
|
908
|
+
if (spec.optionalRegistration && err instanceof PipelineMcpMissingCredentialError) return { skipped: {
|
|
909
|
+
missingEnv: err.missingEnv,
|
|
910
|
+
name: spec.name,
|
|
911
|
+
reason: `missing ${err.headerName} credentials`
|
|
912
|
+
} };
|
|
913
|
+
throw err;
|
|
914
|
+
}
|
|
886
915
|
}
|
|
887
916
|
if (!spec.command) throw new PipelineMcpInstallError(`MCP server ${spec.name} is stdio but has no command.`);
|
|
888
917
|
return {
|
|
@@ -914,8 +943,7 @@ function resolveMcpHeaderValue(serverName, headerName, header) {
|
|
|
914
943
|
const rawValue = process.env[source.env];
|
|
915
944
|
if (rawValue && rawValue.trim().length > 0) return `${source.prefix ?? ""}${rawValue}${source.suffix ?? ""}`;
|
|
916
945
|
}
|
|
917
|
-
|
|
918
|
-
throw new PipelineMcpInstallError([`MCP server ${serverName} requires ${headerName} credentials before it can be registered.`, `Set ${envNames} and re-run pipeline init.`].join("\n"));
|
|
946
|
+
throw new PipelineMcpMissingCredentialError(serverName, headerName, header.sources.map((source) => source.env));
|
|
919
947
|
}
|
|
920
948
|
function assertDefaultSkillsInstalled(cwd) {
|
|
921
949
|
const paths = defaultSkillPaths();
|
|
@@ -935,7 +963,7 @@ async function initPipelineProject(options = {}) {
|
|
|
935
963
|
const paths = Object.keys(files);
|
|
936
964
|
const conflicts = paths.filter((path) => existsSync(join(cwd, path)));
|
|
937
965
|
if (conflicts.length > 0 && !options.overwrite) throw new PipelineInitError(conflicts);
|
|
938
|
-
await (options.mcpInstaller ?? installDefaultMcpsWithCli)(DEFAULT_MCP_INSTALLS, cwd);
|
|
966
|
+
const mcpInstallResult = await (options.mcpInstaller ?? installDefaultMcpsWithCli)(DEFAULT_MCP_INSTALLS, cwd);
|
|
939
967
|
await (options.skillInstaller ?? installDefaultSkillsWithCli)(DEFAULT_SKILL_INSTALLS, cwd);
|
|
940
968
|
const skillPaths = assertDefaultSkillsInstalled(cwd);
|
|
941
969
|
for (const [path, content] of Object.entries(files)) {
|
|
@@ -949,10 +977,18 @@ async function initPipelineProject(options = {}) {
|
|
|
949
977
|
...existsSync(join(cwd, "skills-lock.json")) ? ["skills-lock.json"] : []
|
|
950
978
|
];
|
|
951
979
|
loadPipelineConfig(cwd);
|
|
952
|
-
return {
|
|
980
|
+
return {
|
|
981
|
+
files: generatedPaths,
|
|
982
|
+
skippedMcps: mcpInstallResult?.skipped ?? []
|
|
983
|
+
};
|
|
953
984
|
}
|
|
954
985
|
function formatPipelineInitResult(result) {
|
|
955
|
-
|
|
986
|
+
const skippedMcps = result.skippedMcps ?? [];
|
|
987
|
+
return [
|
|
988
|
+
"Initialized pipeline scaffold:",
|
|
989
|
+
...result.files.map((path) => `create ${path}`),
|
|
990
|
+
...skippedMcps.flatMap((skip) => [`Skipped MCPM registration for ${skip.name}: ${skip.reason}.`, `Set ${skip.missingEnv.join(" or ")} before retrying MCPM registration. The generated MCP entry remains in .mcp.json.`])
|
|
991
|
+
].join("\n");
|
|
956
992
|
}
|
|
957
993
|
function hostResourceInput(host) {
|
|
958
994
|
return [
|
package/package.json
CHANGED