Verify account
Verify a MeetStream account's configuration before building. Checks API key validity, which transcription providers are configured (deepgram / assemblyai / sarvam / jigsawstack / meetstream), webhook URL reachability, and surfaces any missing provider keys. Use when the user says "verify my MeetStream account", "check setup", "which providers do I have", "test API key", "diagnose meetstream", or before any other build skill runs.From its SKILL.md
npx -y skills add meetstream-ai/claude-plugin --skill verify-accountAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
8.2 KB, as published. Nobody here has run it
Verify MeetStream Account
Run a comprehensive health check on the user's MeetStream account before scaffolding anything. Catches the most common cause of build failures: missing or misconfigured provider keys.
Step 0: Make sure there's an API key to verify
If MEETSTREAM_API_KEY is unset, invoke the getting-started skill first — without an account + key, there's nothing to verify. Signup is at https://app.meetstream.ai.
What to do
-
Get the API key. Ask the user, or read it from
MEETSTREAM_API_KEYenv var. Never log it. -
Run the verification script. Write it to a temp file and execute. Capture the report.
-
Present the report. Clearly mark each provider as ✅ configured / ❌ not configured / ⚠️ unknown.
-
Recommend next steps based on what works.
The verification script
Write this to /tmp/meetstream_verify.py and run it:
#!/usr/bin/env python3
"""MeetStream account verifier. Reports which providers/features are configured."""
import json, os, sys, urllib.request, urllib.error
KEY = os.environ.get("MEETSTREAM_API_KEY") or (sys.argv[1] if len(sys.argv) > 1 else "")
if not KEY:
print("❌ No API key. Set MEETSTREAM_API_KEY or pass as arg.")
sys.exit(2)
BASE = "https://api.meetstream.ai/api/v1"
HEADERS = {"Authorization": f"Token {KEY}", "Content-Type": "application/json"}
def req(method, path, body=None):
url = f"{BASE}{path}"
data = json.dumps(body).encode() if body else None
r = urllib.request.Request(url, headers=HEADERS, data=data, method=method)
try:
resp = urllib.request.urlopen(r)
return resp.status, json.loads(resp.read())
except urllib.error.HTTPError as e:
try: body = json.loads(e.read())
except: body = {}
return e.code, body
except Exception as e:
return 0, {"error": str(e)}
print("=" * 60)
print("MeetStream account verification")
print("=" * 60)
# 1. API key validity
print("\n[1] API key validity")
code, body = req("GET", "/bots")
if code == 200:
print(f" ✅ API key valid. {len(body.get('bots',[]))} bots visible on first page.")
elif code in (401, 403):
print(f" ❌ API key rejected (HTTP {code}). Get a fresh key at https://app.meetstream.ai/api-keys")
sys.exit(1)
else:
print(f" ⚠ Unexpected: HTTP {code}: {body}")
# 2. Probe each post-call provider by creating a tiny test bot and reading the error message
print("\n[2] Post-call transcription providers")
providers = {
"deepgram": {"deepgram": {"model": "nova-3", "language": "en"}},
"assemblyai": {"assemblyai": {"speech_models": ["universal-2"], "language_code": "en_us",
"speaker_labels": True, "punctuate": True, "format_text": True,
"filter_profanity": False, "redact_pii": False,
"auto_chapters": False, "entity_detection": False}},
"sarvam": {"sarvam": {"model": "saaras:v3", "language_code": "en-IN", "mode": "transcribe", "with_diarization": True}},
"jigsawstack": {"jigsawstack": {"language": "auto", "translate": False, "by_speaker": True}},
"meetstream": {"meetstream": {"language": "en", "translate": False}},
}
probe_bots = []
for name, provider in providers.items():
payload = {
"meeting_link": f"https://meet.google.com/verify-probe-{name}",
"bot_name": f"verify-{name}",
"video_required": False,
"recording_config": {
"transcript": {"provider": provider},
"retention": {"type": "timed", "hours": 1},
},
"automatic_leave": {
"waiting_room_timeout": 600, "everyone_left_timeout": 600,
"voice_inactivity_timeout": 600, "in_call_recording_timeout": 600,
"recording_permission_denied_timeout": 300,
},
}
code, body = req("POST", "/bots/create_bot", payload)
if code == 201:
# Provider config accepted by API. transcript_id presence indicates the provider is set up.
tid = body.get("transcript_id")
probe_bots.append(body.get("bot_id"))
if tid:
print(f" ✅ {name:12} configured (transcript_id reserved)")
else:
print(f" ⚠ {name:12} accepted but no transcript_id returned")
elif code == 400:
# 400 often indicates config validation issue (could be missing key)
msg = body.get("message", str(body))[:100]
print(f" ❌ {name:12} rejected: {msg}")
else:
print(f" ⚠ {name:12} HTTP {code}: {body}")
# 3. Probe streaming providers (similar — but with live webhook URL)
print("\n[3] Streaming providers")
streaming = {
"meetstream_streaming": {"meetstream_streaming": {}},
"meeting_captions": {"meeting_captions": {}},
}
for name, provider in streaming.items():
payload = {
"meeting_link": f"https://meet.google.com/verify-probe-{name}",
"bot_name": f"verify-{name}",
"video_required": False,
"live_transcription_required": {"webhook_url": "https://example.com/probe"},
"recording_config": {
"transcript": {"provider": provider},
"retention": {"type": "timed", "hours": 1},
},
"automatic_leave": {
"waiting_room_timeout": 600, "everyone_left_timeout": 600,
"voice_inactivity_timeout": 600, "in_call_recording_timeout": 600,
"recording_permission_denied_timeout": 300,
},
}
code, body = req("POST", "/bots/create_bot", payload)
if code == 201:
probe_bots.append(body.get("bot_id"))
print(f" ✅ {name:24} configured")
else:
msg = body.get("message", str(body))[:100]
print(f" ❌ {name:24} HTTP {code}: {msg}")
# 4. Endpoint reachability
print("\n[4] Core endpoints")
for label, method, path in [
("GET /bots", "GET", "/bots"),
("GET /calendar", "GET", "/calendar"),
("GET /mia (list agents)", "GET", "/mia"),
]:
code, _ = req(method, path)
status = "✅" if 200 <= code < 300 else f"⚠ {code}"
print(f" {status:6} {label}")
# 5. Cleanup probe bots
print("\n[5] Cleanup probe bots")
for bid in probe_bots:
code, _ = req("DELETE", f"/bots/{bid}/delete")
print(f" {'✅' if code == 200 else '⚠ ' + str(code)} deleted {bid}")
print("\n" + "=" * 60)
print("Done. See summary above.")
print("=" * 60)
How to read the report
- ✅ on a provider = it's configured in your account, post-call/streaming bots with that provider will work
- ❌ on a provider = key missing or invalid in MeetStream dashboard. Either add the key at https://app.meetstream.ai → Integrations, or use a different provider
meetstream_streamingandmeeting_captionsshould always be ✅ — they don't need external keys
After the report
Recommend a build strategy based on what's configured:
- All ✅ → user can pick any provider freely. Recommend
deepgram(post-call accuracy) ormeetstream_streaming(live, free) - Only
meetstream_streamingworks → recommend the live-streaming pattern +/transcribefallback with whatever they DO have for post-call - No post-call providers, only
meetstream_streaming→ guide them to add at least one provider key in the dashboard before building the notetaker; otherwise/transcribewill fail too
Safety note
This skill does create real bots (1 per provider) against fake meeting links and immediately deletes them. The bots never join any actual meeting. Cleanup is automatic via DELETE /bots/{id}/delete. The script will print each deletion so the user can audit.
The destructive
/deleteis intentional and explicit in this verification context — the bots created here have no value. Outside this skill, do NOT auto-call/delete.