katman-mcp 0.2.0 → 0.3.0
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 +48 -42
- package/dist/license.js +201 -12
- package/dist/meta.js +25 -13
- package/dist/plans.js +13 -6
- package/dist/tools/account/account.js +19 -10
- package/dist/tools/account/cli.js +4 -3
- package/dist/tools/account/index.js +1 -1
- package/dist/tools/account/upsell.js +156 -39
- package/dist/tools/crawl/audit/report.js +2 -2
- package/dist/tools/crawl/cli.js +18 -6
- package/dist/tools/crawl/index.js +39 -8
- package/dist/tools/crawl/scan/framework.js +4 -1
- package/dist/tools/method/core/lint.js +15 -1
- package/dist/tools/method/core/prompt.js +2 -1
- package/dist/tools/method/data/_store.js +17 -0
- package/dist/tools/method/data/anatomy.js +12 -141
- package/dist/tools/method/data/appendices.js +22 -202
- package/dist/tools/method/data/cloudflare.js +28 -192
- package/dist/tools/method/data/evidence.js +18 -137
- package/dist/tools/method/data/geo-jobs.js +8 -128
- package/dist/tools/method/data/landing.js +14 -67
- package/dist/tools/method/data/lessons.js +16 -127
- package/dist/tools/method/data/measurement.js +38 -142
- package/dist/tools/method/data/offsite.js +16 -148
- package/dist/tools/method/data/pages.js +16 -167
- package/dist/tools/method/data/prompts.js +8 -633
- package/dist/tools/method/data/publish.js +14 -113
- package/dist/tools/method/data/research.js +14 -131
- package/dist/tools/method/data/roadmap.js +12 -105
- package/dist/tools/method/data/traps.js +6 -74
- package/dist/tools/method/data/verify.js +12 -88
- package/dist/tools/method/data/viral-list.js +12 -39
- package/dist/tools/method/lib/prompt-lookup.js +18 -0
- package/dist/tools/method/mcp/resources.js +4 -3
- package/dist/tools/visibility/index.js +2 -2
- package/dist/tools/visibility/monitoring.js +3 -0
- package/package.json +5 -3
- package/server.json +3 -3
|
@@ -1,39 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
};
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
{ n: 7, item: { en: "og:image", tr: "og:image" }, verdict: "partly", google: { en: "The Open Graph protocol is for share previews. Since 2 March 2026 Google also uses og:image as a source for the search thumbnail; no effect on indexing or ranking.", tr: "Açık Grafik protokolü paylaşım önizlemesi içindir. Google 2 Mart 2026’dan beri og:image’i arama küçük resmi için bir kaynak olarak da kullanıyor; dizine alma ya da sıralama etkisi yok." } },
|
|
14
|
-
{ n: 8, item: { en: "Broken links", tr: "Kırık linkler" }, verdict: "partly", google: { en: "404s don't penalise the rest of the site on their own; a URL returning 4xx drops out of the index. Fix broken links to important pages; 301 moved URLs.", tr: "404’ler sitenin geri kalanını tek başına cezalandırmaz; 4xx dönen adres dizinden düşer. Önemli sayfalara giden kırık linkleri düzeltin, taşınan adresi 301 ile yönlendirin." } },
|
|
15
|
-
{ n: 9, item: { en: "Heading hierarchy", tr: "Başlık hiyerarşisi" }, verdict: "partly", google: { en: "Heading order doesn't matter to Google; a clean order helps screen readers. Bing wants a logical H1–H6 structure.", tr: "Google için başlıkların sırası önemli değil; düzgün sıra ekran okuyuculara yardım eder. Bing mantıklı bir H1–H6 düzeni istiyor." } },
|
|
16
|
-
{ n: 10, item: { en: "Backlink strategy", tr: "Backlink stratejisi" }, verdict: "partly", google: { en: "Google finds pages mostly through links and expects links to come naturally over time. Buying links and excessive link exchanges are spam.", tr: "Google sayfaları çoğunlukla linklerle bulur ve linklerin zamanla doğal gelmesini bekler. Link satın almak ve aşırı link takası spam." } },
|
|
17
|
-
{ n: 11, item: { en: "Clean URLs", tr: "Temiz URL’ler" }, verdict: "partly", google: { en: "Readable words, hyphens instead of underscores. Words in the URL have very little ranking effect. If you change a live URL, a 301 is a must.", tr: "Okunabilir kelimeler, alt çizgi yerine tire. URL’deki kelimelerin sıralamaya etkisi çok az. Canlı adresi değiştirirseniz 301 şart." } },
|
|
18
|
-
{ n: 12, item: { en: "Internal links", tr: "İç linkler" }, verdict: "true", google: { en: "Link to every page you care about from another page. A link must be an <a> with an href; the link text should describe the target.", tr: "Önem verdiğiniz her sayfaya başka bir sayfadan link verin. Link, href’i olan bir <a> olmalı; link metni hedefi anlatmalı." } },
|
|
19
|
-
{ n: 13, item: { en: "Canonical tags", tr: "Canonical etiketleri" }, verdict: "partly", google: { en: "rel=canonical is a strong signal but a hint, not a rule. None of it is mandatory; Google also picks the canonical itself.", tr: "rel=canonical güçlü bir işaret ama kural değil, ipucu. Hiçbiri zorunlu değil; Google kanonik adresi kendisi de seçer." } },
|
|
20
|
-
{ n: 14, item: { en: "HTTPS everywhere", tr: "HTTPS zorunlu" }, verdict: "true", google: { en: "HTTPS is a small ranking signal and part of page experience. Among equivalent pages Google picks the HTTPS one as canonical.", tr: "HTTPS küçük bir sıralama işareti ve sayfa deneyiminin parçası. Google eşdeğer sayfalarda HTTPS olanı kanonik seçer." } },
|
|
21
|
-
{ n: 15, item: { en: "Compress images", tr: "Görselleri sıkıştır" }, verdict: "true", google: { en: "Images are often the biggest part of page weight. The benefit is indirect: speed and LCP. WebP and AVIF are supported.", tr: "Görseller çoğu zaman sayfa boyutunun en büyük parçası. Faydası dolaylı: hız ve LCP. WebP ve AVIF destekleniyor." } },
|
|
22
|
-
{ n: 16, item: { en: "Schema markup", tr: "Schema işaretlemesi" }, verdict: "partly", google: { en: "Only makes you eligible for rich results, no guarantee; must match the visible content. The HowTo rich result was retired in 2023, the FAQ rich result on 7 May 2026.", tr: "Yalnızca zengin sonuca aday yapar, garanti vermez; görünen içerikle aynı olmalı. HowTo zengin sonucu 2023’te, SSS zengin sonucu 7 Mayıs 2026’da kalktı." } },
|
|
23
|
-
{ n: 17, item: { en: "Verify Search Console", tr: "Search Console doğrula" }, verdict: "partly", google: { en: "Not required to be indexed; most pages are found on their own. It's a monitoring and debugging tool (URL Inspection, sitemap report).", tr: "İndekslenmek için gerekmez; sayfaların çoğu kendiliğinden bulunur. İzleme ve hata ayıklama aracıdır (URL denetimi, sitemap raporu)." } },
|
|
24
|
-
{ n: 18, item: { en: "One H1 per page", tr: "Sayfada tek H1" }, verdict: "myth", google: { en: "According to Google there's no ideal number of headings; more than one H1 is fine.", tr: "Google’a göre ideal bir başlık sayısı yok; birden fazla H1 sorun değil." } },
|
|
25
|
-
{ n: 19, item: { en: "Write a robots.txt", tr: "robots.txt yaz" }, verdict: "partly", google: { en: "Not mandatory: if robots.txt returns 404, Google treats it as no restrictions. It manages crawling, not indexing; it doesn't hide a page from Google.", tr: "Zorunlu değil: robots.txt 404 dönerse Google kısıtlama yok sayar. Taramayı yönetir, dizine almayı değil; bir sayfayı Google’dan saklamaz." } },
|
|
26
|
-
{ n: 20, item: { en: "Mobile friendly", tr: "Mobil uyum" }, verdict: "true", google: { en: "Google indexes and ranks the mobile version of the site. Responsive design is recommended; content, headings and schema must be the same on mobile.", tr: "Google sitenin mobil hâlini dizine alır ve sıralar. Duyarlı tasarım önerilir; içerik, başlıklar ve schema mobilde de aynı olmalı." } },
|
|
27
|
-
];
|
|
28
|
-
export const VIRAL_LIST_MISLEADING = [
|
|
29
|
-
{ en: "One H1: according to Google there's no ideal number of headings. One H1 is a tidy habit, not a ranking rule.", tr: "Tek H1: Google’a göre ideal bir başlık sayısı yok. Tek H1 düzenli bir alışkanlık, sıralama kuralı değil." },
|
|
30
|
-
{ en: "“Write a robots.txt”: you can do without one. Written wrong, it does harm: Disallow: / closes the whole site; closing a noindex page in robots.txt hides the noindex from Google.", tr: "“robots.txt yaz”: Yazmasanız da olur. Yanlış yazarsanız zarar verir: Disallow: / bütün siteyi kapatır; noindex’li bir sayfayı robots.txt’de kapatırsanız Google noindex’i göremez." },
|
|
31
|
-
{ en: "Schema: no rich-result guarantee. HowTo was retired in 2023, the FAQ rich result on 7 May 2026.", tr: "Schema: Zengin sonuç garantisi yok. HowTo 2023’te, SSS zengin sonucu 7 Mayıs 2026’da Google’dan kalktı." },
|
|
32
|
-
{ en: "Search Console: not needed to get indexed; needed to see the errors.", tr: "Search Console: İndekslenmek için gerekmez; hatayı görmek için gerekir." },
|
|
33
|
-
{ en: "Backlink “strategy”: bought links and link exchanges are in Google's spam policy. Links come when you publish something others want to quote.", tr: "Backlink “stratejisi”: Satın alınan link ve link takası Google’ın spam politikasında. Link, başkasının alıntılamak isteyeceği bir şey yayınlayınca gelir." },
|
|
34
|
-
{ en: "The real gap: the three things that most often make a vibe-coded site invisible aren't on the list at all — text in JavaScript, soft 404s, and open preview copies.", tr: "Asıl eksik: Vibe-coded bir siteyi en sık görünmez yapan üç şey listede hiç yok: metnin JavaScript’te olması, sahte 404’ler, açık kalmış önizleme kopyaları." },
|
|
35
|
-
];
|
|
36
|
-
export const VIRAL_LIST_FOUND = {
|
|
37
|
-
en: "Not on the list, found on katman.pro: AI training bots (GPTBot, ClaudeBot, CCBot, Bytespider) were getting 403 because of Cloudflare's legacy “Block AI bots” toggle. The list's biggest gap: if a bot can't get through the door, none of the other 20 items matter to the assistant.",
|
|
38
|
-
tr: "Listede yok, katman.pro’da bulduk: Yapay zekâ eğitim botları (GPTBot, ClaudeBot, CCBot, Bytespider) Cloudflare’deki eski “Block AI bots” düğmesi yüzünden 403 alıyordu. Listenin en büyük eksiği bu: bot kapıdan giremiyorsa diğer 20 maddenin asistan tarafında karşılığı yok.",
|
|
39
|
-
};
|
|
1
|
+
// Filled from katman.pro at run time for a paid key (see _store.js); the package carries no method text.
|
|
2
|
+
import { onMethod } from "./_store.js";
|
|
3
|
+
export let VERDICT_LABEL = {};
|
|
4
|
+
export let VIRAL_LIST = [];
|
|
5
|
+
export let VIRAL_LIST_FOUND = {};
|
|
6
|
+
export let VIRAL_LIST_MISLEADING = [];
|
|
7
|
+
onMethod((d) => {
|
|
8
|
+
if (d.VERDICT_LABEL !== undefined) VERDICT_LABEL = d.VERDICT_LABEL;
|
|
9
|
+
if (d.VIRAL_LIST !== undefined) VIRAL_LIST = d.VIRAL_LIST;
|
|
10
|
+
if (d.VIRAL_LIST_FOUND !== undefined) VIRAL_LIST_FOUND = d.VIRAL_LIST_FOUND;
|
|
11
|
+
if (d.VIRAL_LIST_MISLEADING !== undefined) VIRAL_LIST_MISLEADING = d.VIRAL_LIST_MISLEADING;
|
|
12
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Look-ups over the prompt book. Kept out of data/prompts.ts so every data module holds data only: the published
|
|
2
|
+
// build replaces data modules with stubs filled from katman.pro (scripts/postbuild.mjs, src/tools/method/data/_store.ts).
|
|
3
|
+
import { PLACEHOLDERS, PROMPTS } from "../data/prompts.js";
|
|
4
|
+
export function getPrompt(id) {
|
|
5
|
+
const m = /^p?\s*(\d{1,2})$/i.exec(id.trim());
|
|
6
|
+
const norm = m ? `P${Number(m[1])}` : id.trim().toUpperCase();
|
|
7
|
+
return PROMPTS.find((p) => p.id === norm);
|
|
8
|
+
}
|
|
9
|
+
export function promptPlaceholders(p) {
|
|
10
|
+
const found = new Set();
|
|
11
|
+
for (const text of [p.body.en, p.body.tr]) {
|
|
12
|
+
for (const m of text.matchAll(/\{([a-z_]+)\}/g)) {
|
|
13
|
+
if (PLACEHOLDERS.includes(m[1]))
|
|
14
|
+
found.add(m[1]);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return [...found];
|
|
18
|
+
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
// MCP resources: the method, checklists, content rules, raw prompts and the current project's research.md.
|
|
2
|
-
// Each needs a plan like the tools do: the method texts need "start" (
|
|
2
|
+
// Each needs a plan like the tools do: the method texts need "start" (Katman Pro), research.md "research",
|
|
3
3
|
// the prompt bodies "prompts" (Katman Pro). The resource list itself stays visible.
|
|
4
4
|
import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
5
5
|
import { resolveRoot } from "../../../context.js";
|
|
6
|
-
import { PROMPTS
|
|
6
|
+
import { PROMPTS } from "../data/prompts.js";
|
|
7
|
+
import { getPrompt } from "../lib/prompt-lookup.js";
|
|
7
8
|
import { contentRulesMd, methodOverviewMd, prepublishChecklistMd, rawPromptMd, siteAuditChecklistMd } from "../data/render.js";
|
|
8
9
|
import { loadConfigSafe, loadResearchSafe, loadRuns } from "../lib/state.js";
|
|
9
10
|
import { renderResearchMd } from "../core/research.js";
|
|
@@ -45,7 +46,7 @@ export function registerMethodResources(server, ctx) {
|
|
|
45
46
|
if (!p)
|
|
46
47
|
return md(uri, `Unknown prompt "${raw}". Valid ids: ${PROMPTS.map((x) => x.id).join(", ")}.`);
|
|
47
48
|
// The prompt book is Katman Pro content, like the katman_prompt tool: the titles stay listed, the prompt bodies
|
|
48
|
-
// need Pro (
|
|
49
|
+
// need Pro (an older Audit Week doesn't include them).
|
|
49
50
|
const then = `Then read this resource again, or call katman_prompt {"id": "${p.id}"} to get it filled with this project's data.`;
|
|
50
51
|
return gated(ctx, uri, "prompts", `${p.id} · ${p.title.en}`, then, () => rawPromptMd(p, "en"));
|
|
51
52
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Visibility module: measures whether AI assistants name, recommend and cite the brand.
|
|
2
2
|
// Tools: katman_visibility_run (OpenRouter, user's key, dry run first) and katman_manual_check (no API cost: the user
|
|
3
|
-
// pastes consumer-app answers), both
|
|
3
|
+
// pastes consumer-app answers), both Katman Pro; katman_setup_monitoring (GitHub Actions, Pro).
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import { resolveRoot, rootWarning } from "../../context.js";
|
|
6
6
|
import { fail, ok } from "../../util.js";
|
|
@@ -88,7 +88,7 @@ export function registerVisibilityTools(server, ctx) {
|
|
|
88
88
|
inputSchema: {
|
|
89
89
|
project_root: projectRoot,
|
|
90
90
|
schedule: z.string().optional().describe('Cron (UTC), default "0 6 * * 1" (Mondays 06:00). The book re-measures every 14 days: "0 6 1,15 * *".'),
|
|
91
|
-
include_audit: z.boolean().optional().describe("Also run the live site audit each time (default true)."),
|
|
91
|
+
include_audit: z.boolean().optional().describe("Also run the live site audit each time (default true). Each audit counts as one of the plan's monthly audits (1 site: 5, 3 sites: 30)."),
|
|
92
92
|
write: z.boolean().optional().describe("Write .github/workflows/katman.yml (default false: preview only)."),
|
|
93
93
|
overwrite: z.boolean().optional().describe("Replace an existing workflow file."),
|
|
94
94
|
max_cost_usd: z.number().positive().optional().describe("Per-run cap passed to katman-mcp check; default: the estimate's high end (at least 2)."),
|
|
@@ -155,6 +155,9 @@ export async function setupMonitoring(root, args) {
|
|
|
155
155
|
"- The book re-measures every 14 days; for that cadence use schedule `0 6 1,15 * *`. Weekly runs show the trend sooner at twice the cost.",
|
|
156
156
|
"- A run whose estimate is above the cap refuses to start (nothing spent). A run that hits 402 (no credit) saves its partial results.",
|
|
157
157
|
"- .katman/cache/ is never committed; .katman/ never contains either key.",
|
|
158
|
+
...(includeAudit
|
|
159
|
+
? ["- Each run's live audit step counts as one audit of your Katman Pro plan for the month (1 site: 5 audits; 3 sites: 30). A weekly schedule uses 4–5 a month, so for the 1-site plan use `0 6 1,15 * *` or pass include_audit: false and audit by hand."]
|
|
160
|
+
: []),
|
|
158
161
|
...notes.map((n) => `- ${n}`),
|
|
159
162
|
];
|
|
160
163
|
return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "katman-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Katman MCP: makes your vibe-coded site readable, quotable and recommendable by ChatGPT, Claude, Gemini and Perplexity. Scans your codebase, audits your live site like AI crawlers do, measures AI visibility with your own OpenRouter key.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -17,10 +17,12 @@
|
|
|
17
17
|
"node": ">=20"
|
|
18
18
|
},
|
|
19
19
|
"scripts": {
|
|
20
|
-
"build": "tsc -p tsconfig.json && node scripts/postbuild.mjs",
|
|
20
|
+
"build": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.json && node scripts/postbuild.mjs",
|
|
21
21
|
"dev": "tsx src/index.ts",
|
|
22
22
|
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
23
|
-
"test": "vitest run"
|
|
23
|
+
"test": "vitest run",
|
|
24
|
+
"smoke": "node scripts/smoke-dist.mjs",
|
|
25
|
+
"prepublishOnly": "npm run build && npm test && node scripts/smoke-dist.mjs"
|
|
24
26
|
},
|
|
25
27
|
"keywords": [
|
|
26
28
|
"mcp",
|
package/server.json
CHANGED
|
@@ -3,20 +3,20 @@
|
|
|
3
3
|
"name": "pro.katman/mcp",
|
|
4
4
|
"title": "Katman",
|
|
5
5
|
"description": "Get your vibe-coded site read, quoted and recommended by ChatGPT, Claude, Gemini and Perplexity.",
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.3.0",
|
|
7
7
|
"websiteUrl": "https://katman.pro/mcp",
|
|
8
8
|
"packages": [
|
|
9
9
|
{
|
|
10
10
|
"registryType": "npm",
|
|
11
11
|
"registryBaseUrl": "https://registry.npmjs.org",
|
|
12
12
|
"identifier": "katman-mcp",
|
|
13
|
-
"version": "0.
|
|
13
|
+
"version": "0.3.0",
|
|
14
14
|
"runtimeHint": "npx",
|
|
15
15
|
"transport": { "type": "stdio" },
|
|
16
16
|
"environmentVariables": [
|
|
17
17
|
{
|
|
18
18
|
"name": "KATMAN_KEY",
|
|
19
|
-
"description": "Required. Your Katman licence key (km_live_…) from katman.pro/app/mcp. Every tool except katman_account needs it with an active plan:
|
|
19
|
+
"description": "Required. Your Katman licence key (km_live_…) from katman.pro/app/mcp. Every tool except katman_account needs it with an active Katman Pro plan: 1 site $49/month (1 site, 5 audits a month) or 3 sites $88/month (3 sites, 30 audits a month), both with every tool. An audit is one run of katman_audit_site, counted per calendar month. Plans: katman.pro/pricing.",
|
|
20
20
|
"isRequired": true,
|
|
21
21
|
"isSecret": true,
|
|
22
22
|
"format": "string"
|