Viikko 7
Tämän viikon tehtävät
Typoja tai epäselvyyksiä tehtävissä?
Tee korjausehdotus editoimalla tätä tiedostoa GitHubissa.
Tehtävien palauttaminen
Tehtävät palautetaan GitHubiin, sekä merkitsemällä tehdyt tehtävät palautussovellukseen https://study.cs.helsinki.fi/stats/courses/ohtu-2026 välilehdelle “my submission”.
Tämän viikon tehtävät 3-8 palautetaan jo edellisillä viikoilla käyttämääsi palautusrepositorioon, hakemiston viikko7 sisälle. Tehtävien 1 ja 2 ei tarvitse näkyä palautuksessa, riittää kun teet tehtävät.
Katso tarkempi ohje palautusrepositorioita koskien täältä.
Tehtävien checkboxien rastit tallentuvat selaimesi paikalliseen muistiin.
1. Git: stash [versionhallinta]
Tehtävien 1 ja 2 ei tarvitse näkyä palautuksessa, riittää kun teet tehtävät
Lue https://git-scm.com/book/en/v2/Git-Tools-Stashing-and-Cleaning kohtaan Creative stashing asti, tai hanki muualta vastaavat tiedot.
Oletetaan että olet repositoriossa, jossa on ainakin kaksi branchia: main ja jokin toinen (kutsutaan sitä tässä nimellä experimental).
Ollessasi main-branchissa tee branchissa oleviin tiedostoihin muutoksia, joita lisäät staging-alueelle ja joitain muutoksia joita et vielä lisää.
Varmista, että komennon git status tulos näyttää suunnilleen seuraavalta
$ git status
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: src/index.py
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
README.md
Pomosi käskee sinua välittömästi tekemään pari muutosta branchiin experimental. Et kuitenkaan halua vielä commitoida mainissa olevia muutoksia. Jos siirryt branchiin experimental tekemättä committia, tulee hirveä sotku, sillä muutokset pysyvät muutoksina toisessakin branchissa. git stash pelastaa tästä tilanteesta:
Stashaa mainissa olevat muutokset
Kokeile ennen ja jälkeen stash-komennon komentoa git status
Siirry branchiin experimental, tee sinne jokin muutos jonka committaat
Palaa jälleen mainiin
Palauta stashatyt muutokset komennolla git stash apply
Varmista että muutokset palasivat
Kuten huomaat, staging-alueelle jo lisätty muutos ei palaa staging-alueelle, vaan joudut lisäämään sen uudelleen. Jos edellisessä komento olisi annettu muodossa git stash apply --index, olisi tilanne palautunut täysin ennalleen.
2. Git: branchin “siirtäminen” [versionhallinta]
Tehtävien 1 ja 2 ei tarvitse näkyä palautuksessa, riittää kun teet tehtävät
Tee repoosi branchi nimeltä haara
Tee mainiin ja haaraan committeja siten että saat aikaan seuraavankaltaisen tilanteen:
Eli sekä main että haara ovat edenneet muutamien commitien verran haarautumisen tapahduttua. Huom: komennolla gitk --all näet kaikki haarat, kokeile!
Yhtäkkiä huomaat, että mainiin tekemäsi asiat eivät olekaan kovin hyviä ja haarassa on paljon parempaa tavaraa, haluaisitkin että haarasta tulisi uusi main. Tämä onnistuu kun menet mainiin ja annat komennon git reset --hard haara
Varmista että komento toimii oikein
Vanhan main-haarankaan tavarat eivät katoa mihinkään, jos niihin jostain syystä vielä halutaan palata. Vanhaan committiin palaaminen onnistuu, jos commitin id on tiedossa. Jos ei, on olemassa muutamia keinoja sen selvittämiseksi.
3. ja 4. (kahden rastin tehtävä) KPS yksin- ja kaksinpeli
Kurssirepositorion hakemistosta viikko7/kivi-paperi-sakset löytyy tutun pelin tietokoneversio.
Kopioi projekti palautusrepositorioosi, hakemiston viikko7 sisälle.
- Ohjelmassa on kolme pelimoodia: ihminen vs. ihminen, ihminen vs. yksinkertainen tekoäly ja ihminen vs. monimutkainen tekoäly
- Koodi sisältää runsaat määrät copy pastea, muutenkaan oliosuunnittelun periaatteet eivät ole vielä alkuperäisellä ohjelmoijalla olleet hallussa
Poista koodista kaikki toisteisuus ja tee siitä rakenteellisesti materiaalin osan 4 hengessä oikeaoppinen
pelaa-metodi tulee toteuttaa template-metodina- Sopivan peliolion (kaksinpeli, helppo yksinpeli, vaikea yksinpeli) luominen tulee toteuttaa staattisen tehdasmetodin, tai funktion avulla
- Pääohjelmalla ei saa olla riippuvuuksia konkreettisiin pelin toteuttaviin luokkiin
Jos teet tehtävän mielestäsi kaikkien tyylisääntöjen mukaan, merkkaa 2 rastia, jos ratkaisusi ei ole kaikin osin tyylikäs, merkkaa yksi rasti.
Vinkki: eräs tapa lähteä liikkeelle on muodostaa yliluokka KiviPaperiSakset, joka sisältää kaikille kolmelle pelityypille yhteisen koodin:
class KiviPaperiSakset:
def pelaa(self):
tuomari = Tuomari()
ekan_siirto = self._ensimmaisen_siirto()
tokan_siirto = self._toisen_siirto(ekan_siirto)
while self._onko_ok_siirto(ekan_siirto) and self._onko_ok_siirto(tokan_siirto):
# ...
print("Kiitos!")
print(tuomari)
def _ensimmaisen_siirto(self):
return input("Ensimmäisen pelaajan siirto: ")
# tämän metodin toteutus vaihtelee eri pelityypeissä
def _toisen_siirto(self, ensimmaisen_siirto):
raise Exception("Tämä metodi pitää korvata aliluokassa")
def _onko_ok_siirto(self, siirto):
return siirto == "k" or siirto == "p" or siirto == "s"
Erilliset peliluokat perivät tämän luokan ja erikoistavat sitä tarpeidensa mukaan:
# luokka perii luokan KiviPaperiSakset
class KPSPelaajaVsPelaaja(KiviPaperiSakset):
# toteutetaan metodi pelityypin mukaisesti
def _toisen_siirto(self, ensimmaisen_siirto):
tokan_siirto = input("Toisen pelaajan siirto: ")
return tokan_siirto
HUOM riippuen siitä miten tehtävän teet, on mahdollista että törmäät seuraavaan virheeseen:
ImportError: cannot import name 'KiviPaperiSakset' from partially initialized module 'kivi_paperi_sakset' (most likely due to a circular import) (/Users/mluukkai/opetus/ohtu2022/ohtu-s22-palautukset/viikko7/kivi-paperi-sakset/src/kivi_paperi
Syynä itselläni oli se, että importtasin seuraavasti
Tiedostossa kivi_paperi_sakset.py:
from kps_pelaaja_vs_pelaaja import KPSPelaajaVsPelaaja
# ...
class KiviPaperiSakset:
# ...
# tehdasfunktio, tarvitsee importteja
def luo_peli(tyyppi):
if tyyppi == 'a':
return KPSPelaajaVsPelaaja()
if tyyppi == 'b':
return KPSTekoaly()
if tyyppi == 'c':
return KPSParempiTekoaly()
return None
ja tiedostossa kps_pelaaja_vs_pelaaja.py:
from kivi_paperi_sakset import KiviPaperiSakset
class KPSPelaajaVsPelaaja(KiviPaperiSakset):
# ...
Kaksi tiedostoa päätyi importtaamaan toisensa, eli syntyi circular import, jota Python ei osaa hanskata. Itse ratkaisin ongelman määrittelemällä tehdasfunktion luo_peli omassa tiedostossaan.
5. Web-käyttöliittymä agentin avulla [tekoäly]
Tehdään edellisen tehtävän kivi-paperi-sakset-pelille agentin avulla web-käyttöliittymä.
Tee palautusrepositorioosi kopio projektin hakemistosta nimellä kivi-paperi-sakset-original, jolloin edellisen tehtävän jälkeinen tilanne jää talteen, ja commitoi
Avaa hakemisto viikko7/kivi-paperi-sakset VS Codessa omana workspacenaan ja luo projektille ohjetiedosto. Kirjaa ohjetiedostoon ainakin seuraavat asiat:
- kyseessä on uv-projekti
- olemassa olevaa koodia tulee hyödyntää mahdollisimman paljon, eikä pelilogiikkaa saa toteuttaa uudelleen
- jos käytössäsi on Mac, sovellus ei saa käyttää porttia 5000, joka on Macissa varattu
Tehdään sovellus muutamassa vaiheessa. Commitoi jokaisen vaiheen jälkeen, näin pääset tarvittaessa palaamaan edelliseen toimivaan tilanteeseen.
Toteuta agentin avulla sovellukselle web-käyttöliittymä. Voit joko suunnitella toteutuksen ensin Plan-tilassa viikon 6 tapaan tai antaa tehtävän suoraan Agent-tilassa (jos Plan puuttuu valikosta, ks. tämä)
Pyydä agenttia tekemään sovellukselle Robot Frameworkilla testit. Varmista, että pystyt suorittamaan testit myös itse.
Pyydä agenttia muuttamaan peliä siten, että se päättyy, kun jompikumpi osapuoli on saavuttanut viisi voittoa
Tee peliin vielä agentin avulla jokin haluamasi muutos
Muuta koodia ilman agentin apua siten, että peli päättyy vasta, kun toisella on vähintään kolme voittoa ja kahden voiton johto.
Pyydä agenttia korjaamaan testit ja laajentamaan niitä ottamaan huomioon uuden lopetuslogiikan
Käy läpi agentin tekemä koodi sekä testit. Jos koodissa on jotain sinulle vierasta, pyydä agenttia selittämään, mistä on kyse
Tehdään vielä koodille katselmointi uudelleenkäytettävän prompt-tiedoston avulla.
Lue ennen jatkamista materiaalin Tekoäly ohjelmistotuotannossa viikon 7 osuuden Agentin laajentaminen ja räätälöinti johdanto ja luku Prompt-tiedostot ja räätälöidyt agentit.
Luo projektiin tiedosto .github/prompts/katselmointi.prompt.md, joka ohjeistaa agenttia katselmoimaan projektin koodin ja raportoimaan löydökset. Katselmoinnin tulee tarkastella ainakin seuraavia asioita:
- osan 4 suunnitteluperiaatteet, erityisesti toisteisuus ja turhat riippuvuudet
- testien kattavuus ja laatu
- tietoturva, esim. onko sovellus käynnistetty
debug=True-asetuksella, onko koodissa kovakoodattuja salaisuuksia ja validoidaanko käyttäjän syöte
Agentit ottavat helposti oikoteitä: “katselmointi” tulkitaan pelkkien viimeisimpien muutosten katselmoinniksi, vain osa tiedostoista luetaan, tai työ delegoidaan aliagentille, jolle annetaan alkuperäistä kapeampi tehtävänanto. Kirjaa siksi prompt-tiedostoon myös työskentelytapa ja raportin muoto:
- katselmointi kohdistuu koko projektiin, eikä sitä saa rajata git diffiin eli viimeisimpiin muutoksiin
- agentti muodostaa ensin luettelon projektin kaikista lähdekoodi- ja testitiedostoista ja käy jokaisen läpi
- agentti tekee katselmoinnin itse, eikä delegoi sitä aliagentille
- agentti ei muuta tiedostoja katselmoinnin aikana
- jokainen näkökulma käsitellään omassa osiossaan, ja jos jostain näkökulmasta ei löydy huomautettavaa, se kerrotaan perusteluineen
- jokaisesta löydöksestä kerrotaan tiedosto ja rivit sekä korjausehdotus
- raportin lopussa luetellaan kaikki läpikäydyt tiedostot
Huomioita prompt-tiedoston käytöstä:
- VS Code etsii prompt-tiedostoja workspacen juuren hakemistosta .github/prompts, eli tiedosto tulee luoda hakemistoon viikko7/kivi-paperi-sakset/.github/prompts, ja VS Codessa tulee olla auki projektin hakemisto
- prompt-tiedostot toimivat ainoastaan VS Coden Local-harnessissa (ks. tämä). Muissa harnesseissa, kuten Copilot, prompt-tiedostoa ei ladata, ja komento ei tee sitä mitä tiedostossa pyydetään
Valitse Chat-näkymän alalaidasta harnessiksi Local ja suorita katselmointi chatissa komennolla /katselmointi
Tarkista, noudattiko agentti prompt-tiedoston ohjeita: kävikö se läpi kaikki tiedostot, ja onko raportti pyydetyn muotoinen (voit kysyä tätä agentilta). Jos ei, pyydä agenttia parantamaan tarvittaessa prompt-tiedostoa ja tekemään uusi katselmointi.
Korjaa (itse tai agentin avulla) ainakin yksi katselmoinnin löydös ja commitoi
Kirjoita raportti kokemuksistasi hakemistoon viikko7 talletettavaan tiedostoon agent.md
Kerro raportissa
- Päätyikö agentti toimivaan ratkaisuun, ja miten varmistuit siitä?
- Kuinka paljon jouduit ohjaamaan agenttia matkan varrella?
- Kuinka hyviä agentin tekemät testit olivat?
- Onko agentin tekemä koodi ymmärrettävää, ja miten agentti muutti edellisessä tehtävässä tekemääsi koodia?
- Oliko itse tehtävän muutoksen tekeminen helppoa?
- Noudattiko agentti prompt-tiedoston ohjeita? Miten varmistit sen, ja pitikö prompt-tiedostoa muuttaa?
- Mitä katselmointi löysi, ja olivatko löydökset aiheellisia?
- Mitä uutta opit?
6. MCP ja skillsit [tekoäly]
Agentti pystyy toimimaan vain niillä työkaluilla, jotka sillä on käytössään. VS Coden agentti osaa lukea ja muokata tiedostoja sekä suorittaa komentoja terminaalissa, mutta se ei esimerkiksi näe, miltä edellisessä tehtävässä tehty web-käyttöliittymä näyttää selaimessa. MCP (Model Context Protocol) on avoin standardi, jonka avulla agentille voidaan lisätä uusia työkaluja MCP-palvelimina.
Lue ennen aloittamista materiaalin luku MCP eli Model Context Protocol.
Tehtävässä on kaksi osaa:
- otetaan käyttöön valmis MCP-palvelin, jonka avulla agentti voi käyttää selainta ja testata edellisessä tehtävässä tehdyn web-käyttöliittymän
- tallennetaan käyttöliittymän testausohjeet skillsiksi, jolloin agentti osaa testata käyttöliittymän jatkossa omatoimisesti
Seuraavassa tehtävässä toteutetaan vielä oma MCP-palvelin.
Valmiin palvelimen käyttö
Playwright on selainautomaatiotyökalu, jolla voidaan ohjelmallisesti avata web-sivuja, klikkailla niitä ja täyttää lomakkeita. Playwright MCP -palvelin tarjoaa nämä toiminnot agentin työkaluiksi, eli sen avulla agentti pystyy käyttämään selainta kuten ihminen. Palvelimen käyttö edellyttää, että koneellesi on asennettu Node.js (versio 18 tai uudempi).
Node.js:n asennus
Tarkista ensin, onko Node.js jo asennettu, komennolla
node --version. Jos komento tulostaa version 18 tai uudemman, voit jatkaa. Huomaa, että viikon 3 Robot Framework -tehtävien robotframework-browser-batteries sisältää oman Node.js:n, joka ei ole käytettävissä komentoriviltä, joten Node.js on todennäköisesti asennettava erikseen.
- Mac: asenna Homebrew’lla komennolla
brew install nodetai lataa asennusohjelma (versio LTS) osoitteesta https://nodejs.org/- Windows: lataa asennusohjelma (versio LTS) osoitteesta https://nodejs.org/ tai asenna komennolla
winget install OpenJS.NodeJS.LTS- Linux: jakeluiden paketinhallinnan Node.js-versio on usein vanha, joten asenna mieluummin nvm:n avulla: asenna ensin nvm sen ohjeiden mukaan ja sen jälkeen Node.js komennolla
nvm install --ltsAsennuksen mukana tulee myös komento
npx, jolla VS Code käynnistää palvelimen. Käynnistä VS Code asennuksen jälkeen uudelleen, jotta se löytää komennot.
VS Code lukee MCP-palvelinten määrittelyt (tiedosto .vscode/mcp.json) ja skillsit (hakemisto .github/skills) workspacen juuresta, samoin kuin prompt-tiedostot. Työskentele siis edelleen siten, että VS Codessa on auki hakemisto viikko7/kivi-paperi-sakset.
Lisää edellisen tehtävän projektiin tiedosto .vscode/mcp.json, jolla Playwright MCP otetaan käyttöön:
{
"servers": {
"playwright": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@playwright/mcp@latest", "--browser", "chromium"]
}
}
}
Optio -y hyväksyy paketin latauksen automaattisesti, ja --browser chromium määrittelee käytettäväksi selaimeksi Playwrightin oman Chromiumin.
Käynnistä palvelin klikkaamalla tiedostossa palvelimen nimen "playwright" yläpuolella näkyvää Start-linkkiä, ja varmista chatin työkaluvalikosta (Configure Tools, syöttökentän alapalkin työkalukuvake), että palvelimen työkalut ovat agentin käytössä

Jos palvelin ei käynnisty
Palvelimen lokit näet valitsemalla Start-linkin vierestä More… ja sieltä Show Output. Yleisin syy ongelmiin on se, että VS Code ei löydä komentoa
npx. Näin käy etenkin, jos Node.js on asennettu nvm:llä.Taustaa: kun komento, kuten
npx, annetaan ilman polkua, käyttöjärjestelmä etsii sitä ympäristömuuttujanPATHluettelemista hakemistoista.PATHon kaksoispisteillä (Windowsissa puolipisteillä) erotettu lista hakemistoja, ja sen arvon näet terminaalissa komennollaecho $PATH. Jokainen ohjelma perii ympäristömuuttujat ohjelmalta, joka sen käynnisti. TerminaalinPATHmuodostuu, kun shell lukee käynnistyessään alustustiedostonsa, esim. ~/.zshrc tai ~/.bashrc. Esimerkiksi nvm lisää Node.js:n hakemistonPATH:iin juuri alustustiedostossa, jotennpxlöytyy terminaalista. VS Code ja sen käynnistämät MCP-palvelimet eivät kuitenkaan välttämättä saa käyttöönsä samaaPATH:ia, jolloinnpxei löydy.Ongelma korjautuu kirjoittamalla konfiguraatioon
npx:n koko polku. Selvitä polku terminaalissa komennollawhich npx(Windowsissawhere npx). Koskanpxtarvitsee lisäksi komentoanodeja muita komentoja, lisää myös kohtaenv, jossa määritelläänPATH. Kopioi sen arvoksi terminaalinPATHkomennonecho $PATHtulosteesta (Windowsin PowerShellissä$env:PATH). Huomaa, ettäenv-kohdanPATHkorvaa kokoPATH:n, joten mukana on oltava myös järjestelmän omat hakemistot, kuten /usr/bin ja /bin. Esim. nvm:ää käyttävällä Macilla konfiguraatio voi näyttää seuraavalta:{ "servers": { "playwright": { "type": "stdio", "command": "/Users/kayttaja/.nvm/versions/node/v24.21.0/bin/npx", "args": ["-y", "@playwright/mcp@latest", "--browser", "chromium"], "env": { "PATH": "/Users/kayttaja/.nvm/versions/node/v24.21.0/bin:/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin" } } } }Esimerkin
PATHsisältää nvm:n Node.js-hakemiston, Homebrew’n hakemistot (/usr/local/bin ja /opt/homebrew/bin) sekä macOS:n järjestelmähakemistot. Korvaa polut omilla poluillasi. Jos palvelin käynnistyy mutta selain ei aukea, asenna Playwrightin Chromium komennollanpx playwright install chromium.
Käynnistä kivi-paperi-sakset-sovellus ja pyydä agenttia pelaamaan selaimella yksi peli jokaisessa pelimoodissa ja raportoimaan, toimiiko käyttöliittymä odotetusti
Seuraa, mitä agentti tekee selaimessa. Löysikö agentti käyttöliittymästä ongelmia?
Skills käyttöliittymän testaamiseen
Edellä agentille piti kertoa erikseen, että käyttöliittymä testataan selaimella ja mitä siinä tulee tarkastaa. Jos testaus halutaan tehdä jokaisen käyttöliittymämuutoksen jälkeen, ohjeiden toistaminen joka kerta on työlästä. Ohjeet voisi kirjata ohjetiedostoon, mutta silloin ne olisivat agentin kontekstissa jokaisessa pyynnössä, myös silloin kun niitä ei tarvita.
Skills ratkaisee tämän: agentti näkee aluksi vain skillsin kuvauksen ja lataa varsinaiset ohjeet kontekstiinsa vasta, kun käsillä oleva tehtävä vastaa kuvausta.
Lue ennen jatkamista materiaalin luku Skillsit. Tallennetaan käyttöliittymän testausohjeet skillsiksi.
Luo projektiin tiedosto .github/skills/ui-testaus/SKILL.md, joka ohjeistaa agenttia testaamaan sovelluksen käyttöliittymän selaimella
Tiedoston alussa on YAML-muotoinen otsake, jossa määritellään skillsin nimi (name) ja kuvaus (description). Nimen tulee olla sama kuin skillsin hakemiston nimi, eli tässä ui-testaus. Otsakkeen jälkeen tulevat varsinaiset ohjeet tavallisena Markdownina:
---
name: ui-testaus
description: 'Testaa sovelluksen web-käyttöliittymän selaimella. Käytä kun käyttöliittymää on muutettu tai kun pyydetään testaamaan käyttöliittymä.'
---
1. Käynnistä sovellus komennolla ...
2. ...
Kuvaus on skillsin tärkein osa, sillä agentti näkee aluksi ainoastaan sen ja päättää sen perusteella, milloin skillsiä käytetään. Kuvauksessa kannattaa siis kertoa sekä mitä skills tekee, että missä tilanteissa sitä tulee käyttää.
Kirjaa ohjeisiin ainakin
- miten sovellus käynnistetään ja missä portissa se toimii
- että testaus tehdään selaimella Playwright MCP:n avulla
- mitkä pelimoodit ja tilanteet testataan, esim. pelin päättyminen kahden voiton johtoon ja virheellinen syöte
- miten agentin tulee raportoida tulokset, esim. lista testatuista tilanteista ja niiden lopputuloksista
Varmista, että VS Code löytää skillsin. Kirjoita chatiin komento /skills, joka listaa agentin käytössä olevat skillsit:

Projektin omat skillsit näkyvät otsikon project alla. Otsikon plugin alla ovat VS Coden laajennusten mukanaan tuomat skillsit, joten listasi voi näyttää erilaiselta kuin kuvassa. Jos skillsiä ei löydy, tarkista tiedoston sijainti ja nimi sekä se, että otsakkeen name vastaa hakemiston nimeä.
Aloita uusi chat-keskustelu ja pyydä agenttia esim. tarkastamaan, toimiiko sovelluksen käyttöliittymä, mainitsematta skillsiä. Tarkista chatin työvaiheista, latasiko agentti skillsin käyttöönsä. Jos ei ladannut, paranna kuvausta ja kokeile uudelleen
Skillsin voi käynnistää myös itse kirjoittamalla chatiin / ja skillsin nimen. Kokeile komentoa /ui-testaus
Tee käyttöliittymään jokin pieni muutos ja pyydä agenttia varmistamaan, että sovellus toimii edelleen. Käyttääkö agentti skillsiä?
Commitoi muutokset
Kirjoita raportti kokemuksistasi hakemistoon viikko7 talletettavaan tiedostoon mcp.md
Kerro raportissa
- Miten Playwright MCP -palvelimen käyttö sujui, ja löysikö agentti selaimella ongelmia?
- Ottiko agentti skillsin käyttöön ilman erillistä pyyntöä? Miten kuvauksen sanamuoto vaikutti siihen?
- Milloin käyttäisit skillsiä, milloin prompt-tiedostoa ja milloin ohjetiedostoa?
7. Oma MCP-palvelin [tekoäly]
Lue ennen aloittamista materiaalin luku Oma MCP-palvelin.
Valmiiden palvelinten lisäksi MCP-palvelimen voi toteuttaa myös itse. Näin agentin käyttöön saa esim. oman sovelluksen toiminnallisuutta tai yrityksen sisäistä dataa. Toteutetaan oma MCP-palvelin, jonka avulla agentti voi tehdä kyselyjä NHL-tilastoihin viikon 6 koodia hyödyntäen.
Palvelin on tavallinen Python-ohjelma, jonka funktiot merkitään dekoraattorilla @mcp.tool(). MCP-kirjasto muodostaa funktioiden tyyppimäärittelyistä ja docstringeistä työkalujen kuvaukset, joiden perusteella agentti päättää, milloin ja miten työkaluja kutsutaan. VS Code käynnistää palvelimen taustalle, ja agentti kommunikoi sen kanssa standardisyötteen ja -tulosteen välityksellä.
Kopioi viikon 6 projekti query-language palautusrepositorioosi hakemiston viikko7 sisälle ja avaa se VS Codessa omana workspacenaan
Lisää projektiin MCP-kirjasto komennolla uv add "mcp[cli]"
Luo tiedosto src/mcp_server.py, jonka pohjana voit käyttää seuraavaa:
from mcp.server import MCPServer
from statistics import Statistics
from player_reader import PlayerReader
URL = "https://studies.cs.helsinki.fi/nhlstats/2024-25/players.txt"
stats = Statistics(PlayerReader(URL))
mcp = MCPServer("NHL-tilastot")
@mcp.tool()
def top_scorers(how_many: int) -> list[str]:
"""Return the players with the most points in the NHL 2024-25 season."""
return [str(player) for player in stats.top_scorers(how_many)]
if __name__ == "__main__":
mcp.run()
Huom: MCP-kirjasto kehittyy nopeasti. Jos yllä oleva import ei toimi, käytössäsi on kirjaston vanhempi versio, jossa palvelinluokka on FastMCP ja se importataan from mcp.server.fastmcp import FastMCP.
MCP Inspector on selainpohjainen työkalu, jolla MCP-palvelinta voi testata ilman agenttia. Inspectorilla voi kutsua palvelimen työkaluja käsin ja nähdä, mitä palvelin agentille tarjoaa: työkalujen nimet, kuvaukset ja parametrit.
Käynnistä Inspector projektin hakemistossa komennolla
npx @modelcontextprotocol/inspector uv run python src/mcp_server.py
Komento käynnistää Inspectorin ja avaa sen selaimeen osoitteeseen, joka on muotoa http://127.0.0.1:6274/?MCP_INSPECTOR_API_TOKEN=.... Osoitteen lopussa oleva token suojaa Inspectoria siten, että muut koneella ajettavat ohjelmat eivät pääse käyttämään sitä. Jos selain ei aukea itsestään, kopioi osoite tokeneineen terminaalista.
Yhdistä Inspector palvelimeen
Inspector avautuu Servers-välilehdelle, jossa näkyy käynnistyskomennon perusteella määritelty palvelin uv. Yhdistä palvelimeen kortin oikeassa yläkulmassa olevasta kytkimestä, jolloin kortissa lukee Connected:

Oikeassa reunassa, välilehdellä Protocol, näkyvät Inspectorin ja palvelimen väliset JSON-RPC-viestit. Esimerkiksi viesti tools/list on pyyntö, jolla client kysyy palvelimelta sen tarjoamat työkalut. Samoja viestejä vaihtavat myös VS Code ja palvelin, kun agentti käyttää palvelinta.
Jos viestien tila jää muotoon PENDING, eikä Tools-välilehdellä näy työkaluja, lähetä viesti tools/list uudelleen sen kortin ↻-kuvakkeesta (kuvassa alempi nuoli).
Testaa työkalua top_scorers
Siirry välilehdelle Tools ja valitse listasta top_scorers. Oikealle avautuu työkalun kuvaus, eli funktion docstring, sekä kenttä parametrille How Many. Anna parametrille arvo ja paina Execute Tool, jolloin työkalun palauttama tulos näkyy alapuolella:

Kuvaus ja parametrit ovat juuri sitä tietoa, jonka perusteella agentti päättää, milloin ja miten työkalua käytetään.
Jos palvelin ei käynnisty tai yhdistäminen epäonnistuu, näet virheilmoituksen oikean reunan välilehdeltä Console. Tyypillisiä syitä ovat virhe Python-koodissa tai se, että komento on suoritettu väärässä hakemistossa.
Muista, että palvelin ei saa tulostaa mitään standarditulosteeseen esim. tavallisella print-komennolla, sillä tulosteet sotkevat palvelimen ja Inspectorin välisen kommunikaation. Standardivirhevirtaan tulostaminen (print(..., file=sys.stderr)) on sen sijaan sallittua.
Lisää palvelimelle ainakin seuraavat työkalut:
team_players, joka palauttaa annetun joukkueen pelaajatquery_players, joka palauttaa merkkijonona annetun kyselyn tuloksen käyttäen viikon 6 tehtävän 7parse-funktiota. Jos et tehnyt tehtävää 7, voit toteuttaa työkalun esim. siten, että sille annetaan joukkue sekä maalien ja syöttöjen minimimäärät, ja kysely muodostetaanQueryBuilder-luokan avulla
Voit toteuttaa työkalut itse tai agentin avulla, mutta varmista, että ymmärrät palvelimen koodin. Kirjoita työkaluille kuvaavat docstringit, sillä agentti päättää niiden perusteella, milloin ja miten työkaluja käytetään. Kirjoita työkalujen kuvauksiin myös kyselykielen syntaksi.
Rekisteröi palvelin VS Codeen lisäämällä projektiin tiedosto .vscode/mcp.json:
{
"servers": {
"nhl": {
"type": "stdio",
"command": "uv",
"args": ["run", "--directory", "${workspaceFolder}", "python", "src/mcp_server.py"]
}
}
}
Jos palvelin ei käynnisty, koska VS Code ei löydä komentoa uv, toimi kuten edellisen tehtävän Playwright-palvelimen kohdalla, eli kirjoita konfiguraatioon uv:n koko polku (which uv).
Käynnistä palvelin ja kysy agentilta luonnollisella kielellä kysymyksiä, joihin se tarvitsee palvelimesi työkaluja, esim. “Keillä NYR:n pelaajilla on vähintään 10 maalia mutta alle 20 maalia?” tai “Kuka Edmontonin pelaaja teki eniten pisteitä?”
Seuraa, mitä työkaluja agentti kutsuu ja millä parametreilla
Agentin tekemät työkalukutsut näkyvät chatissa agentin vastauksen työvaiheiden joukossa, esim. query_players – nhl (MCP Server). Avaamalla työkalukutsun näet, mitä palvelin palautti (Output). Kutsun parametrit eivät kuitenkaan välttämättä näy kohdassa Input, jossa saattaa olla ainoastaan palvelimen ja työkalun nimi.
Parametrit saa näkyviin lisäämällä palvelimeen lokituksen. Koska palvelin ei saa tulostaa standarditulosteeseen, kirjoitetaan loki tiedostoon:
from pathlib import Path
LOG_FILE = Path(__file__).parent.parent / "mcp.log"
def log(message: str):
with open(LOG_FILE, "a", encoding="utf-8") as f:
print(message, file=f)
@mcp.tool()
def team_players(team: str) -> list[str]:
"""..."""
log(f"team_players(team={team!r})")
# ...
Loki kirjoitetaan projektin juurihakemiston tiedostoon mcp.log. Lisää tiedosto myös .gitignore:en.
Lokia on kätevintä seurata erillisessä terminaalissa komennolla
tail -f mcp.log
joka näyttää tiedostoon kirjoitettavat rivit sitä mukaa kun niitä syntyy. Windowsin PowerShellissä vastaava komento on Get-Content mcp.log -Wait.
Kokeile, miten docstringien muuttaminen vaikuttaa agentin toimintaan. Palvelin on käynnistettävä uudelleen muutosten jälkeen, esim. tiedoston .vscode/mcp.json palvelimen nimen yläpuolella näkyvän Restart-linkin avulla
Kirjoita raportti kokemuksistasi hakemistoon viikko7 talletettavaan tiedostoon oma_mcp.md
Kerro raportissa
- Osasiko agentti käyttää oman palvelimesi työkaluja oikein?
- Miten docstringit vaikuttivat agentin toimintaan?
- Mitä riskejä liittyisi palvelimeen, joka voisi myös muuttaa dataa, tai joka hakisi dataa epäluotettavista lähteistä?
8. Tekoäly ja minä [tekoäly]
Lue ennen tehtävän tekemistä materiaalin Tekoäly ohjelmistotuotannossa viimeinen luku Lopuksi, joka kokoaa yhteen tekoälyn käyttöön liittyviä riskejä ja tutkimustietoa tekoälyn vaikutuksista ohjelmistotuotantoon.
Kirjoita hakemistoon viikko7 talletettavaan tiedostoon reflektio.md noin sivun (noin 500 sanaa) pohdinta tekoälyn käytöstä ohjelmistokehityksessä
Pohdi kirjoituksessasi ainakin seuraavia:
- Miten tekoälyn käyttösi muuttui kurssin aikana?
- Missä tekoäly auttoi eniten, ja missä siitä oli haittaa?
- Mitkä kurssilla opituista ohjelmistotuotannon käytänteistä ovat mielestäsi tärkeimpiä agentteja käytettäessä?
- Minkälaiset pelisäännöt tekoälyn käytölle sopisit miniprojektisi tiimin kanssa, tai tulevassa työpaikassasi?
9. Kurssipalaute
Anna kurssipalautetta osoitteessa https://norppa.helsinki.fi/targets/112400522/feedback. Voit antaa palautteen myös kokeen jälkeen. Rasti tähän tehtävään on lupaus siitä, että annat palautteen jossain vaiheessa. Palautetta voi antaa välillä 9.–26.12.2026.
HUOM jos menet palautteenanto-osoitteeseen ennen loppupalautteen alkupäivää, näet kurssin “jatkuvan palauten” lomakkeen. Tässä tehtävässä tarkoitetaan kuitenkin 9.12. aukeavaa normaalia loppupalautetta.
Tehtävien palautus
Pushaa kaikki tekemäsi tehtävät (paitsi ne, joissa mainitaan, että tehtävää ei palauteta mihinkään) GitHubiin palautusrepositorioosi ja merkkaa tekemäsi tehtävät palautussovellukseen https://study.cs.helsinki.fi/stats/courses/ohtu-2026