A no-BS, self-hosted URL shortener, AI first with MCP server built in, running on Cloudflare Workers, edge-native, and ridiculously easy to deploy
Drift inferred · capture-to-capture
No drift recorded — single capability capture; advisories appear once its surface changes.
transport stdio · http counts 37 tools · 0 res
· 0 prompts
permission surface via code analysis
tools
-
add_custom_slug
-
add_link_to_bundle
-
archive_bundle
-
compare_links
-
create_bundle
-
create_link
-
delete_bundle
-
delete_link
-
disable_link
-
disable_slug
-
enable_link
-
enable_slug
-
get_bundle
-
get_bundle_analytics
-
get_clicks_by_country
-
get_clicks_by_device
-
get_clicks_by_referrer
-
get_dashboard_stats
-
get_link
-
get_link_analytics
-
get_link_breakdown
-
get_link_qr
-
get_link_timeline
-
get_total_clicks
-
get_trending_links
-
health
-
list_bundle_links
-
list_bundles
-
list_bundles_for_link
-
list_links
-
list_links_by_owner
-
remove_link_from_bundle
-
remove_slug
-
search_links
-
unarchive_bundle
-
update_bundle
-
update_link
prompt-surface
shipped agent-instruction files + hidden-content / dangerous-code findings —
quoted from the analyzed source
analyzed commit ff96eb4 · analyzer v33 · 2w ago
skills & prompt files 1
- agent-rules oddbit-shrtnr-ff96eb4/CLAUDE.md
danger signals2
- dynamic code execution new Function() oddbit-shrtnr-ff96eb4/src/__tests__/unit/client-api-error-toasts.test.ts :71
const factory = new Function( - dynamic code execution new Function() oddbit-shrtnr-ff96eb4/src/__tests__/unit/client-script-escaping.test.ts :55
const factory = new Function("document", code) as (doc: unknown) => {
evidence-backed
findings quoted directly from the published source artifact — not inferred
code files: 246
filesystem 3
- fs oddbit-shrtnr-ff96eb4/browser-extensions/build.mjs :16
import { promises as fs } from "node:fs"; - fs (weak) oddbit-shrtnr-ff96eb4/browser-extensions/scripts/generate-icons.mjs :10
import { promises as fs } from "node:fs"; - fs (weak) oddbit-shrtnr-ff96eb4/browser-extensions/scripts/verify-build.mjs :8
import { promises as fs } from "node:fs";
shell / exec 2
- shell oddbit-shrtnr-ff96eb4/browser-extensions/build.mjs :19
import { spawn } from "node:child_process"; - shell (weak) oddbit-shrtnr-ff96eb4/browser-extensions/scripts/generate-icons.mjs :13
import { spawn } from "node:child_process";
network 26
- net (weak) oddbit-shrtnr-ff96eb4/sdk/typescript/tests/client.test.ts :29
// streaming: the failure mode a rejected fetch() promise cannot reproduce. - net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/admin/widgets/cache-invalidation.test.ts :16
return worker.fetch(new Request("https://x.test" + path, init), env as never, { - net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/admin/widgets/route.test.ts :16
return worker.fetch(new Request("https://x.test" + path), env as any, { - net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/handler/api-keys.test.ts :50
const res = await SELF.fetch( - net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/handler/api-links.test.ts :49
const res = await SELF.fetch( - net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/handler/api-misc.test.ts :31
const res = await SELF.fetch(unauthed("/")); - net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/handler/breakdown-pagination.test.ts :29
const res = await SELF.fetch(new Request("https://shrtnr.test/_/admin/api/keys", { - net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/handler/bundles-api.test.ts :60
const res = await SELF.fetch(authed("owner@x", "/_/admin/api/bundles", { - net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/handler/mcp.test.ts :37
const res = await SELF.fetch( - net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/handler/openapi.test.ts :17
const res = await SELF.fetch( - net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/handler/public-api-range.test.ts :19
const res = await SELF.fetch(new Request("https://shrtnr.test/_/admin/api/keys", { - net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/handler/redirect-kv.test.ts :30
const res = await SELF.fetch(req("cached")); - net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/integration/bundle-aggregation.test.ts :63
const res = await SELF.fetch( - net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/integration/expiration-flow.test.ts :47
const res = await SELF.fetch(req(slug)); - net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/integration/mcp-create-and-redirect.test.ts :66
const res = await SELF.fetch( - net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/integration/redirect-flow.test.ts :60
const redirectRes = await SELF.fetch( - net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/page/bundle-detail-page.test.ts :49
const res = await SELF.fetch(req(`/_/admin/bundles/${bundle.id}`)); - net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/page/bundles-page.test.ts :24
const res = await SELF.fetch(req("/_/admin/bundles")); - net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/page/keys-page.test.ts :40
const res = await SELF.fetch(authed("/_/admin/keys")); - net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/page/link-detail-page.test.ts :23
const res = await SELF.fetch(req(`/_/admin/links/${link.id}`)); - net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/page/links-page.test.ts :26
const res = await SELF.fetch(req("/_/admin/links")); - net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/page/settings-page.test.ts :14
const res = await SELF.fetch(req("/_/admin/settings")); - net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/service/tracking-service.test.ts :30
const res = await SELF.fetch( - net oddbit-shrtnr-ff96eb4/src/client.ts :84
return fetch(API + path, opts).then(function(res) { - net oddbit-shrtnr-ff96eb4/src/index.tsx :117
// confuse fetch() callers expecting JSON. - net oddbit-shrtnr-ff96eb4/src/title-fetch.ts :10
const res = await fetch(url, {
secrets 1
- secrets (weak) oddbit-shrtnr-ff96eb4/sdk/typescript/tests/e2e/e2e.test.ts :17
const API_KEY = process.env.SHRTNR_TEST_API_KEY;
tool registrations 37
- health oddbit-shrtnr-ff96eb4/src/mcp/server.ts :155
- list_links oddbit-shrtnr-ff96eb4/src/mcp/server.ts :169
- get_link oddbit-shrtnr-ff96eb4/src/mcp/server.ts :189
- create_link oddbit-shrtnr-ff96eb4/src/mcp/server.ts :210
- update_link oddbit-shrtnr-ff96eb4/src/mcp/server.ts :257
- disable_link oddbit-shrtnr-ff96eb4/src/mcp/server.ts :277
- enable_link oddbit-shrtnr-ff96eb4/src/mcp/server.ts :294
- add_custom_slug oddbit-shrtnr-ff96eb4/src/mcp/server.ts :311
- disable_slug oddbit-shrtnr-ff96eb4/src/mcp/server.ts :329
- enable_slug oddbit-shrtnr-ff96eb4/src/mcp/server.ts :348
- remove_slug oddbit-shrtnr-ff96eb4/src/mcp/server.ts :367
- get_link_analytics oddbit-shrtnr-ff96eb4/src/mcp/server.ts :386
- search_links oddbit-shrtnr-ff96eb4/src/mcp/server.ts :407
- list_links_by_owner oddbit-shrtnr-ff96eb4/src/mcp/server.ts :436
- get_link_qr oddbit-shrtnr-ff96eb4/src/mcp/server.ts :464
- get_trending_links oddbit-shrtnr-ff96eb4/src/mcp/server.ts :515
- get_dashboard_stats oddbit-shrtnr-ff96eb4/src/mcp/server.ts :535
- get_link_timeline oddbit-shrtnr-ff96eb4/src/mcp/server.ts :554
- get_clicks_by_country oddbit-shrtnr-ff96eb4/src/mcp/server.ts :575
- get_clicks_by_referrer oddbit-shrtnr-ff96eb4/src/mcp/server.ts :595
- get_clicks_by_device oddbit-shrtnr-ff96eb4/src/mcp/server.ts :615
- compare_links oddbit-shrtnr-ff96eb4/src/mcp/server.ts :639
- get_link_breakdown oddbit-shrtnr-ff96eb4/src/mcp/server.ts :659
- get_total_clicks oddbit-shrtnr-ff96eb4/src/mcp/server.ts :681
- delete_link oddbit-shrtnr-ff96eb4/src/mcp/server.ts :700
- list_bundles oddbit-shrtnr-ff96eb4/src/mcp/server.ts :722
- get_bundle oddbit-shrtnr-ff96eb4/src/mcp/server.ts :749
- create_bundle oddbit-shrtnr-ff96eb4/src/mcp/server.ts :769
- update_bundle oddbit-shrtnr-ff96eb4/src/mcp/server.ts :795
- archive_bundle oddbit-shrtnr-ff96eb4/src/mcp/server.ts :816
- unarchive_bundle oddbit-shrtnr-ff96eb4/src/mcp/server.ts :834
- delete_bundle oddbit-shrtnr-ff96eb4/src/mcp/server.ts :852
- add_link_to_bundle oddbit-shrtnr-ff96eb4/src/mcp/server.ts :870
- remove_link_from_bundle oddbit-shrtnr-ff96eb4/src/mcp/server.ts :889
- list_bundle_links oddbit-shrtnr-ff96eb4/src/mcp/server.ts :908
- list_bundles_for_link oddbit-shrtnr-ff96eb4/src/mcp/server.ts :925
- get_bundle_analytics oddbit-shrtnr-ff96eb4/src/mcp/server.ts :942
install hooks 1
- prepublishOnly oddbit-shrtnr-ff96eb4/sdk/typescript/package.json :28
npm run build
declared dependencies 15
- @modelcontextprotocol/sdk@1.29.0
- @cloudflare/workers-oauth-provider@^0.8.2
- @hono/zod-openapi@^1.5.1
- agents@^0.19.0
- hono@^4.12.32
- jose@^6.2.4
- zod@^4.4.3
- @cloudflare/vitest-pool-workers@^0.18.8
- @cloudflare/workers-types@^5.20260728.1
- @vitest/runner@^4.1.10
- @vitest/snapshot@^4.1.10
- tsx@^4.23.1
- typescript@^6.0.3
- vitest@^4.1.10
- wrangler@^4.114.0
clipboard 2
- navigator.clipboard oddbit-shrtnr-ff96eb4/browser-extensions/src/clipboard.ts :5
if (typeof navigator !== "undefined" && navigator.clipboard?.writeText) { - navigator.clipboard oddbit-shrtnr-ff96eb4/browser-extensions/tests/setup.ts :148
return globalThis.navigator.clipboard as unknown as { writeText: ReturnType<typeof vi.fn> };
perm:untrusted 1
- untrusted oddbit-shrtnr-ff96eb4/src/client.ts :84
return fetch(API + path, opts).then(function(res) {