@typeroll/mcp-server 0.7.4 → 0.7.7
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/dist/index.js +16 -1
- package/dist/install-skills.js +130 -0
- package/dist/tools/pages.js +22 -6
- package/dist/tools/partials.js +9 -4
- package/dist/tools/search.js +6 -3
- package/dist/tools/settings.js +6 -1
- package/package.json +3 -3
- package/skills/README.md +23 -5
- package/skills/tr-blog.md +177 -0
- package/skills/tr-brand.md +169 -0
- package/skills/tr-forms.md +243 -0
- package/skills/tr-import-url.md +173 -0
- package/skills/tr-new-site.md +198 -0
- package/skills/tr-seo.md +179 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tr-new-site
|
|
3
|
+
description: Use when the user wants to create a new Typeroll site from scratch, set up the initial design, or bootstrap a blank site with working header/footer, brand colors, and a homepage. Also triggers on "start a new site", "set up a site for", or "build a website for [company]".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Bootstrap a new Typeroll site
|
|
7
|
+
|
|
8
|
+
Start here when the site already exists as a database record (created via
|
|
9
|
+
the portal UI or API) but has no design, no header/footer, and no pages.
|
|
10
|
+
The goal is to go from blank to a working 4-page site with correct brand
|
|
11
|
+
identity in a single session.
|
|
12
|
+
|
|
13
|
+
## Preconditions
|
|
14
|
+
|
|
15
|
+
- `@typeroll/mcp-server` configured with a valid `TYPEROLL_API_KEY`.
|
|
16
|
+
- The site exists (confirm with `get_site`).
|
|
17
|
+
- You have the customer brief: company name, industry, 2–3 key brand colors,
|
|
18
|
+
tone of voice (formal / friendly / minimal / vibrant), and a list of
|
|
19
|
+
initial pages.
|
|
20
|
+
|
|
21
|
+
## Recipe
|
|
22
|
+
|
|
23
|
+
### 1. Audit current state
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
get_site
|
|
27
|
+
read_site_settings # see what (if anything) is already configured
|
|
28
|
+
list_pages # don't overwrite pages that already exist
|
|
29
|
+
list_partials # check if header/footer already have content
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### 2. Brand + settings
|
|
33
|
+
|
|
34
|
+
One `update_site_settings` call with every field you know:
|
|
35
|
+
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"site_name": "Acme Studio",
|
|
39
|
+
"tagline": "Short, punchy tagline",
|
|
40
|
+
"language": "sv",
|
|
41
|
+
"colors": {
|
|
42
|
+
"primary": "#1a1a2e",
|
|
43
|
+
"secondary": "#16213e",
|
|
44
|
+
"accent": "#e94560",
|
|
45
|
+
"background": "#f5f5f5",
|
|
46
|
+
"surface": "#ffffff",
|
|
47
|
+
"text": "#1a1a2e",
|
|
48
|
+
"text_light": "#6b7280"
|
|
49
|
+
},
|
|
50
|
+
"fonts": {
|
|
51
|
+
"heading": "Playfair Display",
|
|
52
|
+
"body": "Inter",
|
|
53
|
+
"size_base": 16
|
|
54
|
+
},
|
|
55
|
+
"contact": {
|
|
56
|
+
"email": "hej@acme.se",
|
|
57
|
+
"phone": "+46 8 123 456",
|
|
58
|
+
"address": "Drottninggatan 1, 111 51 Stockholm"
|
|
59
|
+
},
|
|
60
|
+
"social": {
|
|
61
|
+
"instagram": "https://instagram.com/acme",
|
|
62
|
+
"linkedin": "https://linkedin.com/company/acme"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Read it back: `read_site_settings` — confirm `updated_fields` includes
|
|
68
|
+
everything you intended.
|
|
69
|
+
|
|
70
|
+
Google Fonts names: use the full display name as it appears on
|
|
71
|
+
fonts.google.com, e.g. "Cormorant Garamond", "DM Sans", "Plus Jakarta Sans".
|
|
72
|
+
|
|
73
|
+
### 3. Header partial
|
|
74
|
+
|
|
75
|
+
Replace the header with a real nav. Keep it simple:
|
|
76
|
+
|
|
77
|
+
```html
|
|
78
|
+
<header class="site-header">
|
|
79
|
+
<div class="header-inner">
|
|
80
|
+
<a class="header-logo" href="/">Acme Studio</a>
|
|
81
|
+
<nav class="header-nav">
|
|
82
|
+
<a href="/om-oss">Om oss</a>
|
|
83
|
+
<a href="/tjanster">Tjänster</a>
|
|
84
|
+
<a href="/kontakt">Kontakt</a>
|
|
85
|
+
</nav>
|
|
86
|
+
</div>
|
|
87
|
+
</header>
|
|
88
|
+
<style>
|
|
89
|
+
.site-header{background:var(--color-primary);padding:1rem 2rem}
|
|
90
|
+
.header-inner{max-width:1080px;margin:0 auto;display:flex;align-items:center;justify-content:space-between}
|
|
91
|
+
.header-logo{color:#fff;text-decoration:none;font-family:var(--font-heading);font-size:1.25rem;font-weight:700}
|
|
92
|
+
.header-nav{display:flex;gap:2rem}
|
|
93
|
+
.header-nav a{color:rgba(255,255,255,0.85);text-decoration:none;font-size:0.9rem;letter-spacing:0.05em;text-transform:uppercase}
|
|
94
|
+
.header-nav a:hover{color:#fff}
|
|
95
|
+
</style>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Use `replace_partial partial_id="header" html_content="..."`.
|
|
99
|
+
|
|
100
|
+
### 4. Footer partial
|
|
101
|
+
|
|
102
|
+
```html
|
|
103
|
+
<footer class="site-footer">
|
|
104
|
+
<div class="footer-inner">
|
|
105
|
+
<p class="footer-brand">Acme Studio</p>
|
|
106
|
+
<p class="footer-tagline">Tagline here</p>
|
|
107
|
+
<div class="footer-links">
|
|
108
|
+
<a href="/om-oss">Om oss</a>
|
|
109
|
+
<a href="/kontakt">Kontakt</a>
|
|
110
|
+
</div>
|
|
111
|
+
<p class="footer-copy">© 2025 Acme Studio. Alla rättigheter förbehållna.</p>
|
|
112
|
+
</div>
|
|
113
|
+
</footer>
|
|
114
|
+
<style>
|
|
115
|
+
.site-footer{background:var(--color-secondary);color:rgba(255,255,255,0.7);padding:3rem 2rem;margin-top:4rem}
|
|
116
|
+
.footer-inner{max-width:1080px;margin:0 auto;text-align:center;display:grid;gap:1rem}
|
|
117
|
+
.footer-brand{font-family:var(--font-heading);font-size:1.5rem;color:#fff;font-weight:700}
|
|
118
|
+
.footer-links{display:flex;justify-content:center;gap:2rem}
|
|
119
|
+
.footer-links a{color:rgba(255,255,255,0.7);text-decoration:none}
|
|
120
|
+
.footer-links a:hover{color:#fff}
|
|
121
|
+
.footer-copy{font-size:0.8rem;opacity:0.5}
|
|
122
|
+
</style>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Use `replace_partial partial_id="footer" html_content="..."`.
|
|
126
|
+
|
|
127
|
+
### 5. Homepage
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
create_page title="Start" slug="" content_mode="html"
|
|
131
|
+
html_content="<full hero + intro HTML>"
|
|
132
|
+
status="published"
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
`slug=""` creates the homepage under `page_id: "home"`. If it already
|
|
136
|
+
exists, use `update_page page_id="home" patch={html_content: "..."}`.
|
|
137
|
+
|
|
138
|
+
A minimal homepage structure:
|
|
139
|
+
- Hero: full-width section with `<h1>`, tagline, one CTA button
|
|
140
|
+
- Intro: 2–3 sentences about what the company does
|
|
141
|
+
- Services/features grid: 3 cards max
|
|
142
|
+
- CTA band: "Kontakta oss" or similar
|
|
143
|
+
|
|
144
|
+
### 6. Inner pages
|
|
145
|
+
|
|
146
|
+
Create each page:
|
|
147
|
+
```
|
|
148
|
+
create_page title="Om oss" slug="om-oss" content_mode="html"
|
|
149
|
+
html_content="..." status="published"
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Standard set: Om oss, Tjänster, Kontakt. Add more if the brief says so.
|
|
153
|
+
|
|
154
|
+
### 7. Preview + iterate
|
|
155
|
+
|
|
156
|
+
```
|
|
157
|
+
get_preview_link # get a signed URL for the whole site
|
|
158
|
+
get_page_preview page_id="home" # get rendered HTML to spot-check
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Share the preview link with the user. Iterate on feedback.
|
|
162
|
+
|
|
163
|
+
### 8. Deploy
|
|
164
|
+
|
|
165
|
+
When the user approves:
|
|
166
|
+
```
|
|
167
|
+
trigger_deploy
|
|
168
|
+
get_deploy_status job_id=<id> # poll until status=succeeded
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Design conventions
|
|
172
|
+
|
|
173
|
+
- **One `<h1>` per page.** SEO and screen reader requirement.
|
|
174
|
+
- **CSS variables for colors.** Always use `var(--color-primary)` etc. in
|
|
175
|
+
partial `<style>` blocks — never hardcode hex values.
|
|
176
|
+
- **Responsive layout.** Use `max-width` on containers, `display:flex`
|
|
177
|
+
or `display:grid` for layouts, and `clamp()` for fluid type.
|
|
178
|
+
- **Scoped styles.** Put `<style>` at the bottom of partial HTML.
|
|
179
|
+
Styles apply to the whole page; prefix class names with the partial ID
|
|
180
|
+
to avoid collisions (`site-header__*`, `site-footer__*`).
|
|
181
|
+
- **Minimal JS.** The platform doesn't bundle JS. If you need interactions,
|
|
182
|
+
write a small `<script>` inside the partial or page; keep it under 50
|
|
183
|
+
lines. Avoid external CDN dependencies in page bodies.
|
|
184
|
+
|
|
185
|
+
## Pitfalls
|
|
186
|
+
|
|
187
|
+
- **Don't create pages that already exist.** Run `list_pages` first;
|
|
188
|
+
if the slug is taken, use `update_page` instead of `create_page`.
|
|
189
|
+
- **Don't hardcode text from settings into partials.** If `site_name`
|
|
190
|
+
is "Acme", the header partial should have literal "Acme" in it —
|
|
191
|
+
there's no template engine. When the name changes the user updates
|
|
192
|
+
the partial.
|
|
193
|
+
- **Google Fonts names are case-sensitive.** "Playfair Display" works;
|
|
194
|
+
"playfair display" or "Playfair-Display" do not.
|
|
195
|
+
- **Empty `custom_css` field.** If you set `custom_css: ""` it's
|
|
196
|
+
stored as an empty string, not removed. Use it only when you have
|
|
197
|
+
global styles that span both partials and pages (e.g. utility classes,
|
|
198
|
+
`@keyframes`, `:root` overrides for things not in `colors`/`fonts`).
|
package/skills/tr-seo.md
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tr-seo
|
|
3
|
+
description: Use when the user asks to improve SEO, fix meta tags, add structured data, check page titles, or audit the site's search visibility. Triggers on "SEO", "meta descriptions", "Google ranking", "structured data", "JSON-LD", "sitemap", "sökoptimering", or "hjälp mig synas på Google".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# SEO audit and improvements for a Typeroll site
|
|
7
|
+
|
|
8
|
+
## What Typeroll handles automatically
|
|
9
|
+
|
|
10
|
+
- `<html lang>` from site `language` setting (per-page override via `language` field)
|
|
11
|
+
- `<title>` = `page.seo_title || page.title + settings.default_seo_suffix`
|
|
12
|
+
- `<meta name="description">` from `page.seo_description`
|
|
13
|
+
- `<meta name="robots">` from `page.noindex`
|
|
14
|
+
- `<meta property="og:*">` Open Graph tags from seo_title, seo_description, og_image
|
|
15
|
+
- `<link rel="canonical">` from `page.canonical_url` (falls back to the page's own URL)
|
|
16
|
+
- Article schema from `kind: "article"` + `author` + `date_published`
|
|
17
|
+
- Page schema from `kind: "page"` (default)
|
|
18
|
+
- `robots.txt` from `settings.robots_txt`
|
|
19
|
+
- Sanitized HTML that preserves semantic structure
|
|
20
|
+
|
|
21
|
+
## Recipe
|
|
22
|
+
|
|
23
|
+
### 1. Audit current state
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
list_pages status="all"
|
|
27
|
+
read_site_settings
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
For each page, check:
|
|
31
|
+
- Is `seo_title` set? (if not, Google uses `title` + suffix — often fine)
|
|
32
|
+
- Is `seo_description` set? (150–160 chars, unique per page, includes keywords)
|
|
33
|
+
- Is `og_image` set for the homepage and key landing pages?
|
|
34
|
+
- Does the page have exactly one `<h1>`?
|
|
35
|
+
|
|
36
|
+
### 2. Fix missing meta descriptions
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
batch_update_pages updates=[
|
|
40
|
+
{page_id: "home", patch: {seo_description: "Acme designar rum..."}},
|
|
41
|
+
{page_id: "om-oss", patch: {seo_description: "Vi är ett..."}},
|
|
42
|
+
{page_id: "tjanster", patch: {seo_description: "Våra tjänster..."}}
|
|
43
|
+
]
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Guidelines:
|
|
47
|
+
- 150–160 characters
|
|
48
|
+
- Include the most important keyword naturally
|
|
49
|
+
- Make it a compelling reason to click, not a summary of the page's nav
|
|
50
|
+
|
|
51
|
+
### 3. Fix page titles
|
|
52
|
+
|
|
53
|
+
SEO title = what Google shows in search results.
|
|
54
|
+
|
|
55
|
+
If `settings.default_seo_suffix` is set (e.g. " — Acme Studio"), every
|
|
56
|
+
page whose `seo_title` is empty will show `title + suffix`. That's usually
|
|
57
|
+
fine for inner pages; set an explicit `seo_title` only when you want
|
|
58
|
+
something different.
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
update_site_settings {"default_seo_suffix": " — Acme Studio"}
|
|
62
|
+
|
|
63
|
+
update_page page_id="home" patch={
|
|
64
|
+
"seo_title": "Acme Studio — Inredningsdesign i Stockholm"
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### 4. Add Open Graph images
|
|
69
|
+
|
|
70
|
+
Set `og_image` on pages that get shared on social media. If the site has
|
|
71
|
+
a branded hero image, upload it:
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
upload_media_from_url url="https://..." alt="Acme Studio — Inredningsdesign"
|
|
75
|
+
# → returns cdn_url
|
|
76
|
+
|
|
77
|
+
batch_update_pages updates=[
|
|
78
|
+
{page_id: "home", patch: {og_image: "<cdn_url>"}},
|
|
79
|
+
{page_id: "om-oss", patch: {og_image: "<cdn_url>"}}
|
|
80
|
+
]
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
OG image dimensions: 1200×630px ideal. The platform doesn't resize —
|
|
84
|
+
use a correctly-sized source image.
|
|
85
|
+
|
|
86
|
+
### 5. Add structured data (JSON-LD)
|
|
87
|
+
|
|
88
|
+
Typeroll auto-generates Article and Page schema, but you can override or
|
|
89
|
+
extend with custom JSON-LD per page. Example: LocalBusiness on the homepage.
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
update_page page_id="home" patch={
|
|
93
|
+
"json_ld": "{\"@context\":\"https://schema.org\",\"@type\":\"LocalBusiness\",\"name\":\"Acme Studio\",\"url\":\"https://acme.se\",\"telephone\":\"+46812345\",\"address\":{\"@type\":\"PostalAddress\",\"streetAddress\":\"Drottninggatan 1\",\"addressLocality\":\"Stockholm\",\"postalCode\":\"111 51\",\"addressCountry\":\"SE\"}}"
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**Important:** JSON-LD goes in the `json_ld` field as a JSON *string*
|
|
98
|
+
(not a nested object). The renderer injects it inside
|
|
99
|
+
`<script type="application/ld+json">`.
|
|
100
|
+
|
|
101
|
+
Common schemas worth adding:
|
|
102
|
+
- Homepage: `LocalBusiness` or `Organization`
|
|
103
|
+
- About: `AboutPage`
|
|
104
|
+
- Contact: `ContactPage`
|
|
105
|
+
- Blog articles: auto-generated from `kind:"article"` + `author`
|
|
106
|
+
- Events: `Event` with `startDate`, `location`
|
|
107
|
+
- Products: `Product` with `offers`
|
|
108
|
+
|
|
109
|
+
### 6. robots.txt
|
|
110
|
+
|
|
111
|
+
The default robots.txt allows all crawlers. Update if needed:
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
update_site_settings {
|
|
115
|
+
"robots_txt": "User-agent: *\nAllow: /\nSitemap: https://acme.se/sitemap.xml"
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Typeroll doesn't generate a sitemap automatically in phase 1. If the
|
|
120
|
+
customer needs one, create a `/sitemap` page with HTML that lists all
|
|
121
|
+
published pages, or write a static `sitemap.xml` as a page with
|
|
122
|
+
`slug: "sitemap.xml"` and HTML-encoded XML (not recommended for large sites).
|
|
123
|
+
|
|
124
|
+
### 7. Canonical URLs
|
|
125
|
+
|
|
126
|
+
Set `canonical_url` when a page has a duplicate (e.g. the same content
|
|
127
|
+
accessible via two slugs after a migration):
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
update_page page_id="tjansterna" patch={
|
|
131
|
+
"canonical_url": "https://acme.se/tjanster",
|
|
132
|
+
"noindex": true
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### 8. Language settings
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
update_site_settings {"language": "sv"}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Per-page override for multilingual content:
|
|
143
|
+
```
|
|
144
|
+
update_page page_id="about-en" patch={"language": "en"}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### 9. Heading audit
|
|
148
|
+
|
|
149
|
+
Use `search_pages` to find structural problems:
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
search_pages contains="<h1" # pages that have at least one H1
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Then `read_page` on pages that seem to have none or multiple. Fix via
|
|
156
|
+
`update_page patch={html_content: "<corrected HTML>"}`.
|
|
157
|
+
|
|
158
|
+
### 10. Deploy
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
trigger_deploy
|
|
162
|
+
get_deploy_status job_id=<id>
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Pitfalls
|
|
166
|
+
|
|
167
|
+
- **Don't stuff keywords.** Write descriptions for humans. Google ignores
|
|
168
|
+
`<meta name="keywords">` (not a field in Typeroll anyway).
|
|
169
|
+
- **JSON-LD is a string, not a nested field.** Pass the entire schema as
|
|
170
|
+
a JSON-encoded string in `json_ld`. The server escapes `</script` before
|
|
171
|
+
injection.
|
|
172
|
+
- **OG images need absolute URLs.** The `cdn.typeroll.com` URLs are always
|
|
173
|
+
absolute — use those.
|
|
174
|
+
- **`canonical_url` + `noindex` together.** If you noindex a page AND set
|
|
175
|
+
canonical, the canonical is redundant (noindexed pages don't pass equity).
|
|
176
|
+
Use one or the other.
|
|
177
|
+
- **Default suffix on homepage looks odd.** "Acme Studio — Acme Studio"
|
|
178
|
+
happens when title="Acme Studio" and suffix=" — Acme Studio". Set an
|
|
179
|
+
explicit `seo_title` for the homepage.
|